Для разработки программ на Java нам потребуется специальный комплект для разработки JDK (Java Development Kit). JDK включает ряд программ и утилит, которые позволяют компилировать, запускать программы на Java, а также выполнять ряд других функций.
JDK от Oracle для Windows (x64), Linux (x64, ARM64) и MacOS (x64, ARM64) доступны по адресу https://www.oracle.com/java/technologies/downloads/
OpenJDK для Windows (x64), Linux (x64, ARM64) и MacOS (x64, ARM64) доступны по адресу https://jdk.java.net/21/
OpenJDK предоставляет только архивы, Oracle также предоставляет установочные пакеты. Рассмотрим установку JDK для различных систем.
Установка на Windows
Установка с помощью установщика
Наиболее распространенный вариант установки JDK на Windows - это применение установщика с официального сайта Oracle. В частности, перейдем на страницу: https://www.oracle.com/java/technologies/downloads/#jdk22-windows
Нажмем на кнопку Next. На следующем экране необходимо указать, в какую папку будет производиться установка:
Оставим выбор папки по умолчанию и нажмем на Next для выполнения установки.
После завершения установки JDK мы увидим вот такое окно:
При установке JDK все файлы по умолчанию помещаются в каталог C:\Program Files\Java\jdk-[номер_версии] (если при установке не было изменено расположение). Так, если мы откроем в нем подкаталог bin, то мы сможем увидеть в нем ряд утилит. Нас прежде всего интересует утилита компилятора javac и утилита java.exe. javac компилирует код на языке Java в бинарный файл, а java.exe позволяет запускать скомпилированный файл:
Установка через пакетный менеджер
Через пакетный менеджер winget также можно установить OpenJDK от Microsoft. Для этого в командной строке/PowerShell надо выполнить команду:
winget install Microsoft.OpenJDK.21
В данном случае устанавливается 21-версия JDK.
Установка на Linux
Если мы используем JDK от Oracle, то в данном случае нам доступен ряд вариантов установки. В частности, перейдем на страницу: https://www.oracle.com/java/technologies/downloads/#jdk22-linux
ARM64 Compressed Archive: архив для систем на архитектуре ARM64
ARM64 RPM Package: RPM-пакет для систем на архитектуре ARM64, которые для управления пакетами применяют RPM (например, Fedora, Suse и т.д.)
x64 Compressed Archive: архив для систем на архитектуре Intel x86-64
x64 Debian Package: Debian-пакет для систем на архитектуре Intel x86-64 (например, Ubuntu, Debian и т.д.)
x64 RPM Package: RPM-пакет для систем на архитектуре Intel x86-64, которые для управления пакетами применяют RPM (например, Fedora, Suse и т.д.)
Если наша операционная система Ubuntu (на платформе Intel x86-64), то выберем пункт x64 Debian Package, и нам загрузится debian-пакет (в моем случае файл "jdk-22_linux-x64_bin.deb"). Для его установки выполним команду
sudo dpkg -i jdk-22_linux-x64_bin.deb
Если у нас операционная система, которая для управления пакетами применяет RPM, например, Fedora, Suse и др, на платформе Intel x86-64, то необходимо выбрать пункт x64 RPM Package. И затем установить загруженный пакет командой
sudo rpm -ivh jdk-22_linux-x64_bin.rpm
Если у нас ОС Fedora, Suse и др, на платформе ARM64, то необходимо выбрать пункт ARM64 RPM Package. И затем установить загруженный пакет командой
sudo rpm -ivh jdk-22_linux-aarch64_bin.rpm
Также для различных операционных систем в репозиториях могут быть доступны пакеты JDK для установки. Например, установка с помощью пакетного менеджера snap:
sudo snap install openjdk
Установка с помощью пакетного менеджера apt:
sudo apt install default-jdk
Установка определенной версии JDK с помощью пакетного менеджера apt:
sudo apt install openjdk-22-jdk-headless
В случае с установкой архивов все идентично для всех основных систем на базе Linux - загружается архив, распаковывается в определенное место. Затем в переменные среды добавляется путь к папке bin распакованного архива.
Установка Java на MacOS
Для установки Java на MacOS перейдем на страницу загрузок на сайте Oracle по адресу https://www.oracle.com/java/technologies/downloads/#jdk21-mac:
Здесь нам доступно 4 варианта пакетов:
ARM64 Compressed Archive: архивный пакет для MacOS на ARM
ARM64 DMG Installer: установщик для MacOS на архитектуре ARM
x64 Compressed Archive: архивный пакет для MacOS на архитектуре Intel x86-64
x64 DMG Installer: установщик для MacOS на архитектуре Intel x86-64
Загрузим и после загрузки запустим пакет установщика. Вначале нам отобразится приветственное окно.
Далее на всех последующих шагах оставим все опции по умолчанию. И после установки нам отобразится окно об ее успешном окончании:
Проверка установки
После установки Java перейдем к командной строке/терминалу и для проверки версии введем команду
java -version
Консоль нам должна в ответ ввести номер только что установленной версии JDK (в моем случае 22-й версии):
java 22 2024-03-19 Java(TM) SE Runtime Environment (build 22+36-2370) Java HotSpot(TM) 64-Bit Server VM (build 22+36-2370, mixed mode, sharing)
Итак, после установки JDK создадим первую программу на Java.
Итак, после установки JDK создадим первое приложение на языке Java. Что необходимо для создания программы на Java? Прежде всего нам надо написать код программы, и для этого нужен текстовый редактор. Можно использовать любой текстовый редактор, например, Notepad++.
И чтобы превратить код программы в исполняемое приложение необходим компилятор. Компилятор устанавливается вместе с JDK.
Итак, создадим на жестком диске какой-нибудь каталог, в котором будут располагаться файлы с исходным кодом на языке Java. Допустим, это будет каталог C:/Java. Затем создадим в этом каталоге текстовый файл, который переименуем в Program.java. Откроем этот файл в любом текстовом редакторе и наберем в нем следующую программу:
1 2 3 4 5 6 7 | public class Program{ public static void main (String args[]){ System.out.println("Hello METANIT.COM!"); }} |
Java является объектно-ориентированным языком, поэтому вся программа представляется в виде набора взаимодействующих классов. В данном случае определен один класс Program.
При определении класса вначале идет модификатор доступа public, который указывает, что данный класс будет доступен всем, то есть мы сможем его запустить из командной строки. Далее идет ключевое слово class, а затем название класса. То есть класс называется Program. После названия в фигурных скобках расположено содержимое класса.
Класс может содержать различные переменные и методы. В данном случае у нас объявлен один метод main. Это главный метод в любой программе на Java, он является входной точкой программы и с него начинается все управление. Он обязательно должен присутствовать в программе.
Метод main также имеет модификатор public. Слово static указывает, что метод main - статический, а слово void - что он не возвращает никакого значения. Позже
мы подробнее разберем, что все это значит.
Далее в скобках у нас идут параметры метода - String args[] - это массив args, который хранит значения типа String, то
есть строки. В данном случае ни нам пока не нужны, но в реальной программе это те строковые параметры, которые передаются при запуске программы из
командной строки.
После списка параметров в фигурных скобках идет тело метода - это собственно те инструкции, которые и будет выполнять метод.
В данном случае фактически определени определена только одна инструкция - вывод на консоль некоторой строки. Для вывода на консоль используется встроенный метод
System.out.println(). В этот метод передается выводимая строка. Каждая инструкция завершается точкой с запятой.
Теперь скомпилируем написанную программу. Откроем командную строку (в Windows) или терминал в Linux/MacOS и введем там соответствующие команды. Первым делом перейдем в каталог, где лежит наш файл с программой с помощью команды cd:
cd C:\Java
В данном случае файл находится в каталоге C:\Java.
Затем cкомпилируем программу с помощью команды
javac Program.java
Компилятор языка Java представляет утилиту javac. Через пробел название нашего файла, который содержит класс программы.
После этого программа компилируется в байт-код, и в каталоге C:\Java можно будет найти новый файл Program.class. Это и будет файл с байт-кодом программы. Теперь нам надо его запустить с помощью утилиты java:
java Program
Здесь уже расширение у файла не надо использовать.
Для ОС Windows весь процесс будет выглядеть следующим образом:
В примере выше весь процесс разбивался на два этапа:
Компилятор javac создает из программы на языке Java файл с расширением
*.class, который содержит байт-код для виртуальной машины Java или JVMУтилита java запускает скомпилированный байт-код из файла с расширением
*.class. То есть происходит выполнение программы
Но в последних версиях Java также стало возможно сразу выполнить код программы на языке Java:
C:\Java>java Program.java Hello METANIT.COM! C:\Java>
В этом случае утилите java передается файл с исходным кодом. При этом файла с расширением *.class не создается.
В прошлой теме мы рассмотрели, как создавать первую программу с последующим ее запуском в командной строке. Для упрощения разработки мы также можем использовать такие инструменты как IDE или интегрированные среды разработки, которые упрощают и ускоряют написание кода и создание приложений. На данный момент наиболее популярной средой разработки для Java является IntelliJ IDEA от компании JetBrains. Рассмотрим, как использовать данную среду.
Прежде всего загрузим установочный дистрибутив с официального сайта https://www.jetbrains.com/idea/download. По этому адресу можно найти пакеты для Windows, MacOS, Linux. Кроме того, сама среда доступна в двух версиях - Ultimate (платная с триальным бесплатным периодом) и Community (бесплатная). В данном случае выберем бесплатную версию Community.
Обратите внимание, что на сайте сначала идет платная Ultimate-версия и только потом бесплатная Community-версия. Эта среда доступна как для платформы Intel x64, так и для платформы ARM64. Для Windows и MacOS доступны установочные пакеты, для Linux доступны только архивы. Однако ряде ОС на Linux, например, на Ubuntu, для установки можно использовать пакетный менеджер snap и установить среду с помощью команды:
sudo snap install intellij-idea-community --classic
Стоит отметить, Community-версия не имеет ряда многих возможностей, которые доступны в Ultimate-версии (в частности, в Community недоступны опции для веб-приложений на Java). Но Community-версия тоже довольно функциональна и тоже позволяет делать довольно много, в том числе приложения на JavaFX и Android.
После установки запустим IntelliJ IDEA и создадим первый проект. Для этого на стартовом экране выберем New Project:
Далее откроется окно создания проекта. В левой части в качестве типа проекта выберем New Project.
В поле Name укажем имя проекта. В моем случае проект будет называться HelloJava.
В поле Location можно указать путь к проекту, если не устраивает путь по умолчанию.
Поскольку мы будем работать с языком Java, в поле Language выберем пункт Java
Кроме того, в поле JDK можно указать путь к Java SDK, который будет использоваться в проекте. Как правило, это поле по умолчанию уже содержит путь к JDK, который установлен на локальном компьютере. Если это поле пусто, то его надо установить.
После этого нажмем на кнопку Create. После этого среда создаст и откроет проект.
В левой части мы можем увидеть структуру проекта. Все файлы с исходным кодом помещаются в папку src. По умолчанию эта папка пуста, никаких файлов кода у нас в проекте пока нет. Поэтому добавим файл с исходным кодом. Для этого нажмем на папку src правой кнопкой мыши и в контекстном меню выберем пункт New -> Java Class:
После этого нам откроется небольшое окошко, в которое надо ввести имя класса. Пусть класс будет называться Program:
После нажатия на клавишу Enter в папку src будет добавлен новый файл с классом java (в случае выше класс Program). А в центральной части откроется его содержимое - собственно исходный код:
Изменим код класса следующим образом:
1 2 3 4 5 6 7 | public class Program { public static void main(String[] args) { System.out.println("Hello METANIT.COM!"); }} |
С помощью зеленой стрелки на панели инструментов или через меню Run -> Run... запустим проект.
И внизу IntelliJ IDEA отобразится окно вывода, где мы можем увидеть результат работы нашей программы.
Еще одной популярной средой программирования под Java является Netbeans. Проект NetBeans во многом поддерживается и спонсируется компанией Oracle, при этом его разработка ведется независимым сообществом разработчиков (Apache NetBeans Community). NetBeans является кроссплатформенным программным обеспечением, поэтому есть версии среды для различных платформ и ОС. Более подробную информацию можно найти на официальном сайте даной среды https://netbeans.apache.org/.
На данный момент последней версией является 12-я версия. Итак, установим последнюю версию NetBeans, загрузив со страницы https://netbeans.apache.org/download/nb121/nb121.html.
На странице загрузки мы можем найти два варианта: скомпилированные бинарные файлы в виде архива (пункт Binaries) и установщики для каждой конкретной операционной системы (пункт Installers). Загрузим среду в скомпилированном, выбрав пункт Binaries.
После выбора этой опции нас переадресует на страницу с непосредственной ссылкой на зеркало для загрузки:
После загрузки распакуем архив в папку, где мы хотим разместить среду Netbeans. Стоит отметить, что после распаковки архива мы можем уже сразу запустить среду, не надо ничего устанавливать. В архиве уже готовые для использования файлы. Для запуска в распакованном архиве в папке bin мы можем найти собственно запускаемые файлы. В случае с ОС Windows это netbeans.exe и netbeans64.exe
Запустим netbeans.exe или netbeans64.exe:
NetBeans довольно интеллектуально понятна, и с ней очень легко работать. Создадим новый проект. Для этого выберем в меню пункт File->New Project.... После этого перед нами откроется окно создания нового проекта:
В окне создания нового проекта выберем в левой колонке первый пункт - Java with Ant, а в правой в качестве типа проекта - Java Application. И нажмем кнопку Next >
При первом создании проекта для Java нам будет предложено активировать соответствующую функцию:
И на данном этапе нажмем на кноку Activate.
Затем откроется окно настроек проекта:
В поле Project Name дадим проекту какое-нибудь название (в моем случае это HelloApp). Для всех остальных полей можно оставить значения по умолчанию. Последнее поле "Create Main Class" указывает, что автоматически в проекте будет создан класс программы HelloApp, который будет находиться в одноименном пакете helloapp. И в завершении создания проекта нажмем на кнопку "Finish". И перед нами откроется новый проект в Netbeans:
Узкое окно слева отображает все открытые проекты и их структуру. В данном случае у нас открыт пока только один проект. А большое окно справа представляет редактор кода с некоторыми дополнительными функциями, как подцветка кода, интеллектуальная подсказка и т.д. Редактор кода уже имеет некоторое содержание по умолчанию:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 | /* * To change this license header, choose License Headers in Project Properties. * To change this template file, choose Tools | Templates * and open the template in the editor. */package helloapp;/** * * @author Eugene */public class HelloApp { /** * @param args the command line arguments */ public static void main(String[] args) { // TODO code application logic here } } |
Здесь, во-первых, много комментариев, которые нам не нужны и которые мы можем удалить. Во-вторых, в начале файла указывается, что класс будет находиться в пакете
helloapp с помощью директивы package: package helloapp;. Затем, как уже рассматривалось в прошлой теме, у нас есть класс программы - класс
HelloApp, который имеет метод main.
Изменим код по умолчанию на следующий, чтобы программа выводила простейшую строку на консоль:
1 2 3 4 5 6 7 8 9 10 | package helloapp;public class HelloApp { public static void main(String[] args) { System.out.println("Hello Java 15 from Netbeans!"); } } |
Теперь запустим проект на выполнение. Для этого на панели инструментов NetBeans нажмем на зеленую стрелочку (либо можно нажать на клавишу F6, либо выбрать в меню пункт Run -> Run Project). И внизу NetBeans откроется окно вывода, в котором мы сможем наблюдать результаты нашей программы:
Фактически это окно вывода эквивалентно консоли за некоторыми исключениями.
Еще одной очень популярной средой для разработки приложений под Java является Eclipse. IDE Eclipse первоначально была создана и развивалась компанией IBM, но впоследствии разработка была выделена в отдельный проект Eclipse Foundation. Eclipse является бесплатной средой, которая к тому же обладает большими возможностями, позволяя создавать на Java самые разные приложения.
Для начала установим последнюю версию Eclipse, которую можно найти по адресу https://www.eclipse.org/downloads/. На странице загрузок найдем рядом с названием текущей версии Eclipse (на момент написания статьи это версия Oxygen) кнопку "Download" и нажмем на нее.
После нажатия на кнопку нас перенаправит собственно на страницу загрузки, где необходимо будет нажать на кнопку "Download" для загруки установочного пакета:
После загрузки установочного пакета запустим его:
По факту Eclipse - это целый набор сред для разных ситуаций и языков программирования. И программа установки предлагает нам выбрать одну из опций для инсталляции. Поскольку мы собираемся работать с Java, то нас будут интересовать в данном случае прежде всего две опции:
Eclipse IDE for Java Developers
Eclipse IDE for Enterprise Java and Web Developers
Первая опция предоставляет базовые возможности для работы с Java, а вторая позволяет также создавать веб-приложения и сервисы. По сути вторая опция включает и первую опцию. Поэтому выберем Eclipse IDE for Enterprise Java and Web Developers.
Далее надо будет указать папку для установки (или оставить выбранную папку по умолчанию), а также указать путь к JDK и нажать на кнопку Install:
Далее надо будет принять лицензионное соглашение:
И затем собственно начнется установка. После установки запустим Eclipse. Вначале будет предложено установить каталог для проектов. Оставим значение по умолчанию и нажмем на кнорку Launch:
Далее перейдем к пункту меню File -> New -> Project:
Далее нам откроется окно выбора шаблона проекта. Выберем Java Project и нажмем на кнопку Next:
Затем будет предложено установить настройки проекта. В частности, в поле Project Name необходимо задать имя проекта. Допустим, оно будет helloapp:
Также обращаю внимание на поле JRE, которое задает используемую версию Java. Здесь можно использовать версию по умолчанию или изменить ее в зависимости от того, какую версию JDK/JRE мы хотим использовать.
Кроме того, в самом низу окна есть поле Create module-info.java file. Пока эта опция не принципиальна, поэтому чтобы не создавать лишние файлы в проекте, можно снять отметку с этого поля.
Все остальные настройки можно оставить по умолчанию, и в конце нажмем на кнопку Finish для создания проекта.
Следующее диалоговое окно спросит, надо ли открывать перспективу проекта:
В данном случае эта возможность не имеет значения, но нажмем на кнопку Open Perspective.
После создания проект будет открыт в Eclipse. Если среда не открывает по умолчанию проект, то необходимо нажать на кнопку Restore:
По умолчанию проект будет пуст.
Все файлы с исходным кодом на Java в проекте помещаются в папку src. Нажмем на нее правой кнопкой мыши и в контекстном меню выберем New -> Class:
Затем откроется окно настройки класса. Здесь в поле Name необходимо задать название класса. Допустим, он будет называться Program. Все остальные настройки можно оставить по умолчанию:
После этого в проект будет добавлен файл Program.java, а в центральной части Eclipse мы сможем увидеть его код. Изменим этот код на следующий:
1 2 3 4 5 6 7 8 | package helloapp;public class Program { public static void main(String[] args) { System.out.println("Hello Eclipse!"); }} |
Для запуска проекта нажмем на панели инструментов на зеленую стрелочку, либо на пункт меню Run -> Run. И внизу среды в поле Console мы увидим результат работы программы (то есть фактически консольный вывод).
Введение в JAVA
Основным строительным блоком программы на языке Java являются инструкции (statement). Каждая инструкция выполняет некоторое действие, например, вызовы методов, объявление переменных и присвоение им значений. После завершения инструкции в Java ставится точка с запятой (;). Данный знак указывает компилятору на конец инструкции. Например:
1 | System.out.println("Hello Java!"); |
Данная строка представляет вызов метода System.out.println, который выводит на консоль строку "Hello Java!". В данном случае вызов
метода является инструкцией и поэтому завершается точкой с запятой.
Кроме отдельных инструкций распространенной конструкцией является блок кода. Блок кода содержит набор инструкций, он заключается в фигурные скобки, а инструкции помещаются между открывающей и закрывающей фигурными скобками:
1 2 3 4 | { System.out.println("Hello!"); System.out.println("Welcome to Java!");} |
В этом блоке кода две инструкции, которые выводят на консоль определенную строку.
Выполнение программы. Метод main
Java является объектно-ориентированным языком, поэтому всю программу можно представить как набор взаимодействующих между собой классов и объектов. В первой главе при создании первого приложения программа была определена следующим образом:
1 2 3 4 5 6 7 | public class Program{ public static void main (String args[]){ System.out.println("Hello Java!"); }} |
То есть основу нашей программы составляет класс Program. При определении класса вначале идет модификатор доступа public, который указывает, что данный класс будет доступен всем, то есть мы сможем его запустить из командной строки. Далее идет ключевое слово class, а затем название класса. После названия класса идет блок кода, в котором расположено содержимое класса.
Входной точкой в программу на языке Java является метод main, который определен в классе Program. Именно с него начинается выполнение программы. Он обязательно должен присутствовать в программе. При этом его заголовок может быть только таким:
1 | public static void main (String args[]) |
При запуске приложения виртуальная машина Java ищет в главном классе программы метод main с подобным заголовком, и после его обнаружения запускает его.
Вначале заголовка метода идет модификатор public, который указывает, что метод будет доступен извне. Слово static указывает, что метод
main - статический, а слово void - что он не возвращает никакого значения. Далее в скобках у нас идут параметры метода - String args[] -
это массив args, который хранит значения типа String, то есть строки. При запуске программы через этот массив мы можем передать в программу различные данные.
После заголовка метода идет его блок, который содержит набор выполняемых инструкций.
Комментарии
Код программы может содержать комментарии. Комментарии позволяют понять смысл программы, что делают те или иные ее части. При компиляции комментарии игнорируются и не оказывают никакого влияния на работу приложения и на его размер.
В Java есть два типа комментариев: однострочный и многострочный. Однострочный комментарий размещается на одной строке после двойного слеша //. А многострочный комментарий заключается между символами /* текст комментария */. Он может размещаться на нескольких строках. Например:
1 2 3 4 5 6 7 8 9 10 11 12 13 | /* многострочный комментарий Объявление нового класса, который содержит код программы*/public class Program{ // начало объявления класса Program // определение метода main public static void main (String args[]){ // объявление нового метода System.out.println("Hello Java!"); // вывод строки на консоль } // конец объявления нового метода} // конец объявления класса Program |
Для хранения данных в программе предназначены переменные. Переменная представляет именованную область памяти, которая хранит значение определенного типа. Каждая переменная имеет тип, имя и значение. Тип определяет, какую информацию может хранить переменная или диапазон допустимых значений.
Переменные объявляются следующим образом:
1 | тип_данных имя_переменной; |
Например, определим переменную, которая будет называться x и будет иметь тип int:
1 | int x; |
В этом выражении мы объявляем переменную x типа int. То есть x будет хранить некоторое число не больше 4 байт.
В качестве имени переменной может выступать любое произвольное название, которое удовлетворяет следующим требованиям:
имя может содержать любые алфавитно-цифровые символы, а также знак подчеркивания, при этом первый символ в имени не должен быть цифрой
в имени не должно быть знаков пунктуации и пробелов
имя не может быть ключевым словом языка Java
Кроме того, при объявлении и последующем использовании надо учитывать, что Java - регистрозависимый язык, поэтому следующие объявления
int num; и int NUM; будут представлять две разных переменных.
Объявив переменную, мы можем присвоить ей значение:
1 2 3 | int x; // объявление переменнойx = 10; // присвоение значенияSystem.out.println(x); // 10 |
Также можно присвоить значение переменной при ее объявлении. Этот процесс называется инициализацией:
1 2 | int x = 10; // объявление и инициализация переменнойSystem.out.println(x); // 10 |
Если мы не присвоим переменной значение до ее использования, то мы можем получить ошибку, например, в следующем случае:
1 2 | int x;System.out.println(x); |
Через запятую можно объявить сразу несколько переменных одного типа:
1 2 3 4 5 | int x, y;x = 10;y = 25;System.out.println(x); // 10System.out.println(y); // 25 |
Также можно их сразу инициализировать:
1 2 3 | int x = 8, y = 15;System.out.println(x); // 8System.out.println(y); // 15 |
Отличительной особенностью переменных является то, что мы можем в процессе работы программы изменять их значение:
1 2 3 4 | int x = 10;System.out.println(x); // 10x = 25;System.out.println(x); // 25 |
Ключевое слово var
Начиная с Java 10 в язык было добавлено ключевое слово var, которое также позволяет определять переменную:
1 2 | var x = 10;System.out.println(x); // 10 |
Слово var ставится вместо типа данных, а сам тип переменной выводится из того значения, которое ей присваивается. Например,
переменной x присваивается число 10, значит, переменная будет представлять тип int.
Но если переменная объявляется с помощью var, то мы обязательно должны инициализировать ее, то есть предоставить ей начальное значение, иначе мы получим ошибку, как, например, в следующем случае:
1 2 | var x; // ! Ошибка, переменная не инициализированаx = 10; |
Константы
Кроме переменных, в Java для хранения данных можно использовать константы. В отличие от переменных константам можно присвоить значение только один раз. Константа объявляется также, как и переменная, только вначале идет ключевое слово final:
1 2 3 | final int LIMIT = 5;System.out.println(LIMIT); // 5// LIMIT=57; // так мы уже не можем написать, так как LIMIT - константа |
Как правило, константы имеют имена в верхнем регистре.
Константы позволяют задать такие переменные, которые не должны больше изменяться. Например, если у нас есть переменная для хранения числа pi, то мы можем объявить ее константой, так как ее значение постоянно.
Одной из основных особенностей Java является то, что данный язык является строго типизированным. А это значит, что каждая переменная и константа представляет определенный тип и данный тип строго определен. Тип данных определяет диапазон значений, которые может хранить переменная или константа.
Итак, рассмотрим систему встроенных базовых типов данных, которая используется для создания переменных в Java. А она представлена следующими типами.
boolean: хранит значение
trueилиfalse12booleanisActive =false;booleanisAlive =true;byte: хранит целое число от
-128до127и занимает 1 байт12bytea =3;byteb =8;short: хранит целое число от
-32768до32767и занимает 2 байта12shorta =3;shortb =8;int: хранит целое число от
-2147483648до2147483647и занимает 4 байта12inta =4;intb =9;long: хранит целое число от
–9 223 372 036 854 775 808до9 223 372 036 854 775 807и занимает 8 байт12longa =5;longb =10;double: хранит число с плавающей точкой от
±4.9*10-324до±1.7976931348623157*10308и занимает 8 байт12doublex =8.5;doubley =2.7;В качестве разделителя целой и дробной части в дробных литералах используется точка.
float: хранит число с плавающей точкой от
-3.4*1038до3.4*1038и занимает 4 байта12floatx =8.5F;floaty =2.7F;char: хранит одиночный символ в кодировке UTF-16 и занимает 2 байта, поэтому диапазон хранимых значений от
0до65535
При этом переменная может принимать только те значения, которые соответствуют ее типу. Если переменная представляет целочисленный тип, то она не может хранить дробные числа.
Целые числа
Все целочисленные литералы, например, числа 10, 4, -5, воспринимаются как значения типа int, однако мы можем присваивать целочисленные литералы другим целочисленным типам: byte, long, short. В этом случае Java автоматически осуществляет соответствующие преобразования:
1 2 3 | byte a = 1;short b = 2;long c = 2121; |
Однако если мы захотим присвоить переменной типа long очень большое число, которое выходит за пределы допустимых значений для типа int, то мы столкнемся с ошибкой во время компиляции:
1 | long num = 2147483649; |
Здесь число 2147483649 является допустимым для типа long, но выходит за предельные значения для типа int. И так как все целочисленные значения по умолчанию расцениваются как значения типа int, то компилятор укажет нам на ошибку. Чтобы решить проблему, надо добавить к числу суффикс l или L, который указывает, что число представляет тип long:
1 | long num = 2147483649L; |
Как правило, значения для целочисленных переменных задаются в десятичной системе счисления, однако мы можем применять и другие системы счисления. Например:
1 2 3 | int num111 = 0x6F; // 16-теричная система, число 111int num8 = 010; // 8-ричная система, число 8int num13 = 0b1101; // 2-ичная система, число 13 |
Для задания шестнадцатеричного значения после символов 0x указывается число в шестнадцатеричном формате. Таким же образом восьмеричное значение указывается после символа 0, а двоичное значение - после символов 0b.
Также целые числа поддерживают разделение разрядов числа с помощью знака подчеркивания:
1 2 3 4 | int x = 123_456;int y = 234_567__789;System.out.println(x); // 123456System.out.println(y); // 234567789 |
Числа с плавающей точкой
При присвоении переменной типа float дробного литерала с плавающей точкой, например, 3.1, 4.5 и т.д., Java автоматически рассматривает этот литерал как значение типа double.
И чтобы указать, что данное значение должно рассматриваться как float, нам надо использовать суффикс f:
1 2 | float fl = 30.6f;double db = 30.6; |
И хотя в данном случае обе переменных имеют практически одно значения, но эти значения будут по-разному рассматриваться и будут занимать разное место в памяти.
Символы и строки
В качестве значения переменная символьного типа получает одиночный символ, заключенный в одинарные кавычки: char ch='e';.
Кроме того, переменной символьного типа также можно присвоить целочисленное значение от 0 до 65535. В этом случае
переменная опять же будет хранить символ, а целочисленное значение будет указывать на номер символа в таблице символов Unicode (UTF-16). Например:
1 2 | char ch=102; // символ 'f'System.out.println(ch); |
Еще одной формой задания символьных переменных является шестнадцатеричная форма: переменная получает значение в шестнадцатеричной форме,
которое следует после символов "\u". Например, char ch='\u0066'; опять же будет хранить символ 'f'.
Символьные переменные не стоит путать со строковыми, 'a' не идентично "a". Строковые переменные представляют объект String, который
в отличие от char или int не является примитивным типом в Java:
1 2 | String hello = "Hello...";System.out.println(hello); |
Кроме собственно символов, которые представляют буквы, цифры, знаки препинания, прочие символы, есть специальные наборы символов, которые называют управляющими последовательностями. Например, самая популярная последовательность - "\n". Она выполняет перенос на следующую строку. Например:
1 2 | String text = "Hello \nworld";System.out.println(text); |
Результат выполнения данного кода:
Hello world
В данном случае последовательность \n будет сигналом, что необходимо сделать перевод на следующую строку.
Начиная с версии 15 Java поддерживает тестовые блоки (text blocks) - многострочный текст, облеченный в тройные кавычки. Рассмотрим, в чем их практическая польза. Например, выведем большой многострочный текст:
1 2 3 4 5 | String text = "Вот мысль, которой весь я предан,\n"+ "Итог всего, что ум скопил.\n"+ "Лишь тот, кем бой за жизнь изведан,\n"+ "Жизнь и свободу заслужил.";System.out.println(text); |
С помощью операции + мы можем присоединить к одному тексту другой, причем продолжение текста может располагаться на следующей строке. Чтобы при выводе текста происходил перенос на следующую строку, применяется последовательность \n.
Результат выполнения данного кода:
Вот мысль, которой весь я предан, Итог всего, что ум скопил. Лишь тот, кем бой за жизнь изведан, Жизнь и свободу заслужил.
Текстовые блоки, которые появились в JDK15, позволяют упростить написание многострочного текста:
1 2 3 4 5 6 7 | String text = """ Вот мысль, которой весь я предан, Итог всего, что ум скопил. Лишь тот, кем бой за жизнь изведан, Жизнь и свободу заслужил. """;System.out.println(text); |
Весь текстовый блок оборачивается в тройные кавычки, при этом не надо использовать соединение строк или последовательность \n для их переноса. Результат выполнения программы будет тем же, что и в примере выше.
Наиболее простой способ взаимодействия с пользователем представляет консоль: мы можем выводить на консоль некоторую информацию или, наоборот, считывать с консоли некоторые данные. Для взаимодействия с консолью в Java применяется класс System, а его функциональность собственно обеспечивает консольный ввод и вывод.
Вывод на консоль
Для создания потока вывода в класс System определен объект out. В этом объекте определен метод println, который позволяет вывести на консоль некоторое значение с последующим переводом курсора консоли на следующую строку. Например:
1 2 3 4 5 6 7 8 | public class Program { public static void main(String[] args) { System.out.println("Hello world!"); System.out.println("Bye world..."); }} |
В метод println передается любое значение, как правило, строка, которое надо вывести на консоль. И в данном случае мы получим
следующий вывод:
Hello world! Bye world...
При необходимости можно и не переводить курсор на следующую строку. В этом случае можно использовать метод System.out.print(), который аналогичен println за тем исключением, что не осуществляет перевода на следующую строку.
1 2 3 4 5 6 7 8 | public class Program { public static void main(String[] args) { System.out.print("Hello world!"); System.out.print("Bye world..."); }} |
Консольный вывод данной программы:
Hello world!Bye world...
Но с помощью метода System.out.print также можно осуществить перевод каретки на следующую строку. Для этого надо использовать escape-последовательность \n:
1 | System.out.print("Hello world \n"); |
Нередко необходимо подставлять в строку какие-нибудь данные. Например, у нас есть два числа, и мы хотим вывести их значения на экран. В этом случае мы можем, например, написать так:
1 2 3 4 5 6 7 8 9 | public class Program { public static void main(String[] args) { int x=5; int y=6; System.out.println("x=" + x + "; y=" + y); }} |
Консольный вывод программы:
x=5; y=6
Но в Java есть также функция для форматированного вывода, унаследованная от языка С: System.out.printf(). С ее помощью мы можем переписать
предыдущий пример следующим образом:
1 2 3 | int x=5;int y=6;System.out.printf("x=%d; y=%d \n", x, y); |
В данном случае символы %d обозначают спецификатор, вместо которого подставляет один из аргументов. Спецификаторов
и соответствующих им аргументов может быть множество. В данном случае у нас только два аргумента, поэтому вместо первого %d
подставляет значение переменной x, а вместо второго - значение переменной y. Сама буква d означает, что данный спецификатор
будет использоваться для вывода целочисленных значений.
Кроме спецификатора %d мы можем использовать еще ряд спецификаторов для других типов данных:
%x: для вывода шестнадцатеричных чисел
%f: для вывода чисел с плавающей точкой
%e: для вывода чисел в экспоненциальной форме, например,
1.3e+01%c: для вывода одиночного символа
%s: для вывода строковых значений
Например:
1 2 3 4 5 6 7 8 9 10 11 | public class Program { public static void main(String[] args) { String name = "Tom"; int age = 30; float height = 1.7f; System.out.printf("Name: %s Age: %d Height: %.2f \n", name, age, height); }} |
При выводе чисел с плавающей точкой мы можем указать количество знаков после запятой, для этого используем спецификатор на %.2f,
где .2 указывает, что после запятой будет два знака. В итоге мы получим следующий вывод:
Name: Tom Age: 30 Height: 1,70
Ввод с консоли
Для получения ввода с консоли в классе System определен объект in. Однако непосредственно через объект
System.in не очень удобно работать, поэтому, как правило, используют класс Scanner, который, в
свою очередь использует System.in. Например, напишем маленькую программу, которая осуществляет ввод чисел:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | import java.util.Scanner;public class Program { public static void main(String[] args) { Scanner in = new Scanner(System.in); System.out.print("Input a number: "); int num = in.nextInt(); System.out.printf("Your number: %d \n", num); in.close(); }} |
Так как класс Scanner находится в пакете java.util, то мы вначале его импортируем с помощью инструкции import java.util.Scanner.
Для создания самого объекта Scanner в его конструктор передается объект System.in. После этого мы можем получать вводимые значения.
Например, в данном случае вначале выводим приглашение к вводу и затем получаем вводимое число в переменную num.
Чтобы получить введенное число, используется метод in.nextInt();, который возвращает введенное с клавиатуры целочисленное значение.
Пример работы программы:
Input a number: 5 Your number: 5
Класс Scanner имеет еще ряд методов, которые позволяют получить введенные пользователем значения:
next(): считывает введенную строку до первого пробела
nextLine(): считывает всю введенную строку
nextInt(): считывает введенное число int
nextDouble(): считывает введенное число double
nextBoolean(): считывает значение boolean
nextByte(): считывает введенное число byte
nextFloat(): считывает введенное число float
nextShort(): считывает введенное число short
То есть для ввода значений каждого примитивного типа в классе Scanner определен свой метод.
Например, создадим программу для ввода информации о человеке:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | import java.util.Scanner;public class Program { public static void main(String[] args) { Scanner in = new Scanner(System.in); System.out.print("Input name: "); String name = in.nextLine(); System.out.print("Input age: "); int age = in.nextInt(); System.out.print("Input height: "); float height = in.nextFloat(); System.out.printf("Name: %s Age: %d Height: %.2f \n", name, age, height); in.close(); }} |
Здесь последовательно вводятся данные типов String, int, float и потом все введенные данные вместе выводятся на консоль. Пример работы программы:
Input name: Tom Input age: 34 Input height: 1,7 Name: Tom Age: 34 Height: 1,70
Обратите внимание, что для ввода значения типа float (то же самое относится к типу double) применяется число "1,7", где разделителем является запятая, а не "1.7", где разделителем является точка. В данном случае все зависит от текущей языковой локализации системы. В моем случае русскоязычная локализация, соответственно вводить необходимо числа, где разделителем является запятая. То же самое касается многих других локализаций, например, немецкой, французской и т.д., где применяется запятая.
Большинство операций в Java аналогичны тем, которые применяются в других си-подобных языках. Есть унарные операции (выполняются над одним операндом), бинарные - над двумя операндами, а также тернарные - выполняются над тремя операндами. Операндом является переменная или значение (например, число), участвующее в операции. Рассмотрим все виды операций.
В арифметических операциях участвуют числа. В Java есть бинарные арифметические операции (производятся над двумя операндами) и унарные (выполняются над одним операндом). К бинарным операциям относят следующие:
+операция сложения двух чисел:
1234inta =10;intb =7;intc = a + b;// 17intd =4+ b;// 11-операция вычитания двух чисел:
1234inta =10;intb =7;intc = a - b;// 3intd =4- a;// -6*операция умножения двух чисел
1234inta =10;intb =7;intc = a * b;// 70intd = b *5;// 35/операция деления двух чисел:
1234inta =20;intb =5;intc = a / b;// 4doubled =22.5/4.5;// 5.0При делении стоит учитывать, что если в операции участвуют два целых числа, то результат деления будет округляться до целого числа, даже если результат присваивается переменной float или double:
12doublek =10/4;// 2System.out.println(k);Чтобы результат представлял число с плавающей точкой, один из операндов также должен представлять число с плавающей точкой:
12doublek =10.0/4;// 2.5System.out.println(k);%получение остатка от деления двух чисел:
1234inta =33;intb =5;intc = a % b;// 3intd =22%4;// 2 (22 - 4*5 = 2)
Также есть две унарные арифметические операции, которые производятся над одним числом: ++ (инкремент) и -- (декремент). Каждая из операций имеет две разновидности: префиксная и постфиксная:
++ (префиксный инкремент)
Предполагает увеличение переменной на единицу, например,
z=++y(вначале значение переменной y увеличивается на 1, а затем ее значение присваивается переменной z)1234inta =8;intb = ++a;System.out.println(a);// 9System.out.println(b);// 9++ (постфиксный инкремент)
Также представляет увеличение переменной на единицу, например,
z=y++(вначале значение переменной y присваивается переменной z, а потом значение переменной y увеличивается на 1)1234inta =8;intb = a++;System.out.println(a);// 9System.out.println(b);// 8-- (префиксный декремент)уменьшение переменной на единицу, например,
z=--y(вначале значение переменной y уменьшается на 1, а потом ее значение присваивается переменной z)1234inta =8;intb = --a;System.out.println(a);// 7System.out.println(b);// 7-- (постфиксный декремент)z=y--(сначала значение переменной y присваивается переменной z, а затем значение переменной y уменьшается на 1)1234inta =8;intb = a--;System.out.println(a);// 7System.out.println(b);// 8
Приоритет арифметических операций
Одни операции имеют больший приоритет, чем другие, и поэтому выполняются вначале. Операции в порядке уменьшения приоритета:
++ (постфиксный инкремент), -- (постфиксный декремент)
++ (префиксный инкремент), -- (префиксный декремент)
* (умножение), / (деление), % (остаток от деления)
+ (сложение), - (вычитание)
Приоритет операций следует учитывать при выполнении набора арифметических выражений:
1 2 3 4 | int a = 8;int b = 7;int c = a + 5 * ++b; System.out.println(c); // 48 |
Вначале будет выполняться операция инкремента ++b, которая имеет больший приоритет - она увеличит значение переменной b и возвратит его в
качестве результата. Затем выполняется умножение 5 * ++b, и только в последнюю очередь выполняется сложение a + 5 * ++b
Скобки позволяют переопределить порядок вычислений:
1 2 3 4 | int a = 8;int b = 7;int c = (a + 5) * ++b; System.out.println(c); // 104 |
Несмотря на то, что операция сложения имеет меньший приоритет, но вначале будет выполняться именно сложение, а не умножение, так как операция сложения заключена в скобки.
Ассоциативность операций
Кроме приоритета операции отличаются таким понятием как ассоциативность. Когда операции имеют один и тот же приоритет, порядок вычисления определяется ассоциативностью операторов. В зависимости от ассоциативности есть два типа операторов:
Левоассоциативные операторы, которые выполняются слева направо
Правоассоциативные операторы, которые выполняются справа налево
Так, некоторые операции, например, операции умножения и деления, имеют один и тот же приоритет. Какой же тогда будет результат в выражении:
1 | int x = 10 / 5 * 2; |
Стоит нам трактовать это выражение как (10 / 5) * 2 или как 10 / (5 * 2)? Ведь в зависимости от трактовки мы получим разные результаты.
Все арифметические операторы (кроме префиксного инкремента и декремента) являются левоассоциативными, то есть выполняются слева направо. Поэтому выражение 10 / 5 * 2 необходимо трактовать как (10 / 5) * 2,
то есть результатом будет 4.
Операции с числами с плавающей точкой
Следует отметить, что числа с плавающей точкой не подходят для финансовых и других вычислений, где ошибки при округлении могут быть критичными. Например:
1 2 | double d = 2.0 - 1.1;System.out.println(d); |
В данном случае переменная d будет равна не 0.9, как можно было бы изначально предположить, а 0.8999999999999999. Подобные ошибки точности возникают из-за того, что на низком уровне для представления чисел с плавающей точкой применяется двоичная система, однако для числа 0.1 не существует двоичного представления, также как и для других дробных значений. Поэтому в таких случаях обычно применяется класс BigDecimal, который позволяет обойти подобные ситуации.
Поразрядные операции выполняются над отдельными разрядами или битами чисел. В данных операциях в качестве операндов могут выступать только целые числа.
Каждое число имеет определенное двоичное представление. Например, число 4 в двоичной системе 100, а число 5 - 101 и так далее.
К примеру, возьмем следующие переменные:
1 2 | byte b = 7; // 0000 0111short s = 7; // 0000 0000 0000 0111 |
Тип byte занимает 1 байт или 8 бит, соответственно представлен 8 разрядами. Поэтому значение переменной b в двоичном коде будет
равно 00000111. Тип short занимает в памяти 2 байта или 16 бит, поэтому число данного типа будет представлено
16 разрядами. И в данном случае переменная s в двоичной системе будет иметь значение 0000 0000 0000 0111.
Для записи чисел со знаком в Java применяется дополнительный код (two's complement), при котором старший разряд является знаковым. Если его значение равно 0, то число положительное, и его двоичное представление не отличается от представления беззнакового числа. Например, 0000 0001 в десятичной системе 1.
Если старший разряд равен 1, то мы имеем дело с отрицательным числом. Например, 1111 1111 в десятичной системе представляет -1. Соответственно, 1111 0011 представляет -13.
Логические операции
Логические операции над числами представляют поразрядные операции. В данном случае числа рассматриваются в двоичном представлении, например, 2 в двоичной системе равно 10 и имеет два разряда, число 7 - 111 и имеет три разряда.
& (логическое умножение)Умножение производится поразрядно, и если у обоих операндов значения разрядов равно 1, то операция возвращает 1, иначе возвращается число 0. Например:
1234567inta1 =2;//010intb1 =5;//101System.out.println(a1&b1);// результат 0inta2 =4;//100intb2 =5;//101System.out.println(a2 & b2);// результат 4В первом случае у нас два числа 2 и 5. 2 в двоичном виде представляет число 010, а 5 - 101. Поразрядное умножение чисел (0*1, 1*0, 0*1) дает результат 000.
Во втором случае у нас вместо двойки число 4, у которого в первом разряде 1, так же как и у числа 5, поэтому здесь результатом операции (1*1, 0*0, 0 *1) = 100 будет число 4 в десятичном формате.
|(логическое сложение)Данная операция также производится по двоичным разрядам, но теперь возвращается единица, если хотя бы у одного числа в данном разряде имеется единица (операция "логическое ИЛИ"). Например:
123456inta1 =2;//010intb1 =5;//101System.out.println(a1|b1);// результат 7 - 111inta2 =4;//100intb2 =5;//101System.out.println(a2 | b2);// результат 5 - 101^(логическое исключающее ИЛИ)Также эту операцию называют XOR, нередко ее применяют для простого шифрования:
1234567intnumber =45;// 1001 Значение, которое надо зашифровать - в двоичной форме 101101intkey =102;//Ключ шифрования - в двоичной системе 1100110intencrypt = number ^ key;//Результатом будет число 1001011 или 75System.out.println("Зашифрованное число: "+encrypt);intdecrypt = encrypt ^ key;// Результатом будет исходное число 45System.out.println("Расшифрованное число: "+ decrypt);Здесь также производятся поразрядные операции. Если у нас значения текущего разряда у обоих чисел разные, то возвращается 1, иначе возвращается 0. Например, результатом выражения 9^5 будет число 12. А чтобы расшифровать число, мы применяем обратную операцию к результату.
~(логическое отрицание)Поразрядная операция, которая инвертирует все разряды числа: если значение разряда равно 1, то оно становится равным нулю, и наоборот.
12bytea =12;// 0000 1100System.out.println(~a);// 1111 0011 или -13
Операции сдвига
Операции сдвига также производятся над разрядами чисел. Сдвиг может происходить вправо и влево.
a<<b- сдвигает число a влево на b разрядов. Например, выражение4<<1сдвигает число 4 (которое в двоичном представлении 100) на один разряд влево, в результате получается число 1000 или число 8 в десятичном представлении.a>>b- смещает число a вправо на b разрядов. Например,16>>1сдвигает число 16 (которое в двоичной системе 10000) на один разряд вправо, то есть в итоге получается 1000 или число 8 в десятичном представлении.a>>>b- в отличие от предыдущих типов сдвигов данная операция представляет беззнаковый сдвиг - сдвигает число a вправо на b разрядов. Например, выражение-8>>>2будет равно 1073741822.
Таким образом, если исходное число, которое надо сдвинуть в ту или другую сторону, делится на два, то фактически получается умножение или деление на два. Поэтому подобную операцию можно использовать вместо непосредственного умножения или деления на два, так как операция сдвига на аппаратном уровне менее дорогостоящая операция в отличие от операции деления или умножения.
Условные выражения представляют собой некоторое условие и возвращают значение типа boolean, то есть значение true (если условие истинно), или значение false (если условие ложно). К условным выражениям относятся операции сравнения и логические операции.
Операции сравнения
В операциях сравнения сравниваются два операнда, и возвращается значение типа boolean - true, если выражение верно,
и false, если выражение неверно.
==сравнивает два операнда на равенство и возвращает
true(если операнды равны) иfalse(если операнды не равны)1234inta =10;intb =4;booleanc = a == b;// falsebooleand = a ==10;// true!=сравнивает два операнда и возвращает
true, если операнды НЕ равны, иfalse, если операнды равны1234inta =10;intb =4;booleanc = a != b;// truebooleand = a !=10;// false< (меньше чем)
Возвращает
true, если первый операнд меньше второго, иначе возвращаетfalse123inta =10;intb =4;booleanc = a < b;// false> (больше чем)
Возвращает
true, если первый операнд больше второго, иначе возвращаетfalse123inta =10;intb =4;booleanc = a > b;// true>= (больше или равно)
Возвращает
true, если первый операнд больше второго или равен второму, иначе возвращаетfalse123booleanc =10>=10;// truebooleanb =10>=4;// truebooleand =10>=20;// false<= (меньше или равно)
Возвращает
true, если первый операнд меньше второго или равен второму, иначе возвращаетfalse123booleanc =10<=10;// truebooleanb =10<=4;// falsebooleand =10<=20;// true
Логические операции
Также в Java есть логические операции, которые также представляют условие и возвращают true или false и обычно объединяют несколько операций сравнения. К логическим операциям относят следующие:
|c=a|b;(c равноtrue, если либо a, либо b (либо и a, и b) равныtrue, иначе c будет равноfalse)&c=a&b;(c равноtrue, если и a, и b равныtrue, иначе c будет равноfalse)!c=!b;(c равноtrue, если b равноfalse, иначе c будет равноfalse)^c=a^b;(c равноtrue, если либо a, либо b (но не одновременно) равныtrue, иначе c будет равноfalse)||c=a||b;(c равноtrue, если либо a, либо b (либо и a, и b) равныtrue, иначе c будет равноfalse)&&c=a&&b;(c равноtrue, если и a, и b равныtrue, иначе c будет равноfalse)
Здесь у нас две пары операций | и || (а также & и &&) выполняют
похожие действия, однако же они не равнозначны.
Выражение c=a|b; будет вычислять сначала оба значения - a и b и на их основе выводить результат.
В выражении же
c=a||b; вначале будет вычисляться значение a, и если оно равно true, то вычисление значения b уже смысла не имеет,
так как у нас в любом случае уже c будет равно true. Значение b будет вычисляться только в том случае, если a равно false
То же самое касается пары операций &/&&. В выражении c=a&b; будут вычисляться оба значения - a и b.
В выражении же c=a&&b; сначала будет вычисляться значение a,
и если оно равно false, то вычисление значения b уже не имеет смысла, так как значение c в любом случае равно false.
Значение b будет вычисляться только в том случае, если a равно true
Таким образом, операции || и && более удобны в вычислениях, позволяя сократить время на вычисление значения выражения и тем самым повышая
производительность. А операции | и & больше подходят для выполнения поразрядных операций над числами.
Примеры:
1 2 3 4 5 6 | boolean a1 = (5 > 6) || (4 < 6); // 5 > 6 - false, 4 < 6 - true, поэтому возвращается trueboolean a2 = (5 > 6) || (4 > 6); // 5 > 6 - false, 4 > 6 - false, поэтому возвращается falseboolean a3 = (5 > 6) && (4 < 6); // 5 > 6 - false, поэтому возвращается false (4 < 6 - true, но не вычисляется)boolean a4 = (50 > 6) && (4 / 2 < 3); // 50 > 6 - true, 4/2 < 3 - true, поэтому возвращается trueboolean a5 = (5 < 6) ^ (4 > 6); // 5 < 6 - true, поэтому возвращается true (4 > 6 - false)boolean a6 = (50 > 6) ^ (4 / 2 < 3); // 50 > 6 - true, 4/2 < 3 - true, поэтому возвращается false |
В завершении рассмотрим операции присваивания, которые в основном представляют комбинацию простого присваивания с другими операциями:
=просто приравнивает одно значение другому:
c=b;+=c+=b;(переменной c присваивается результат сложения c и b)-=c-=b;(переменной c присваивается результат вычитания b из c)*=c*=b;(переменной c присваивается результат произведения c и b)/=c/=b;(переменной c присваивается результат деления c на b)%=c%=b;(переменной c присваивается остаток от деления c на b)&=c&=b;(переменной c присваивается значение c&b)|=c|=b;(переменной c присваивается значение c|b)^=c^=b;(переменной c присваивается значение c^b)<<=c<<=b;(переменной c присваивается значение c<<b)>>=c>>=b;(переменной c присваивается значение c>>b)>>>=c>>>=b;(переменной c присваивается значение c>>>b)
Примеры операций:
1 2 3 4 5 6 7 8 | int a = 5;a += 10; // 15a -= 3; // 12a *= 2; // 24a /= 6; // 4a <<= 4; // 64a >>= 2; // 16System.out.println(a); // 16 |
Приоритет операций
При работе с операциями важно понимать их приоритет, который можно описать следующей таблицей:
expr++ expr-- |
++expr --expr +expr -expr ~ ! |
* / % |
+ - |
<< >> >>> |
< > <= >= instanceof |
== != |
& |
^ |
| |
&& |
|| |
? : (тернарный оператор) |
= += -= *= /= %= &= ^= |= <<= >>= >>>= (операторы присваивания) |
Чем выше оператор в этой таблице, тем больше его приоритет. При этом скобки повышают приоритет операции, используемой в выражении.
Каждый базовый тип данных занимает определенное количество байт памяти. Это накладывает ограничение на операции, в которые вовлечены различные типы данных. Рассмотрим следующий пример:
1 2 | int a = 4;byte b = a; // ! Ошибка |
В данном коде мы столкнемся с ошибкой. Хотя и тип byte, и тип int представляют целые числа. Более того, значение переменной a, которое присваивается переменной типа byte, вполне укладывается в диапазон значений для типа byte (от -128 до 127). Тем не менее мы сталкиваемся с ошибкой на этапе компиляции. Поскольку в данном случае мы пытаемся присвоить некоторые данные, которые занимают 4 байта, переменной, которая занимает всего один байт.
Тем не менее в программе может потребоваться, чтобы подобное преобразование было выполнено. В этом случае необходимо использовать операцию
преобразования типов (операция ()):
1 2 3 | int a = 4;byte b = (byte)a; // преобразование типов: от типа int к типу byteSystem.out.println(b); // 4 |
Операция преобразования типов предполагает указание в скобках того типа, к которому надо преобразовать значение.
Например, в случае операции (byte)a, идет преобразование данных типа int в тип byte. В итоге мы получим значение типа byte.
Явные и неявные преобразования
Когда в одной операции вовлечены данные разных типов, не всегда необходимо использовать операцию преобразования типов. Некоторые виды преобразований выполняются неявно, автоматически.
Автоматические преобразования
Стрелками на рисунке показано, какие преобразования типов могут выполняться автоматически. Пунктирными стрелками показаны автоматические преобразования с потерей точности.
Автоматически без каких-либо проблем производятся расширяющие преобразования (widening) - они расширяют представление объекта в памяти. Например:
1 2 | byte b = 7;int d = b; // преобразование от byte к int |
В данном случае значение типа byte, которое занимает в памяти 1 байт, расширяется до типа int, которое занимает 4 байта.
Расширяющие автоматические преобразования представлены следующими цепочками:
byte -> short -> int -> long
int -> double
short -> float -> double
char -> int
Автоматические преобразования с потерей точности
Некоторые преобразования могут производиться автоматически между типами данных одинаковой разрядности или даже от типа данных с большей разрядностью к
типа с меньшей разрядностью. Это следующие цепочки преобразований: int -> float, long -> float и long -> double.
Они производятся без ошибок, но при преобразовании мы можем столкнуться с потерей информации.
Например:
1 2 3 | int a = 2147483647;float b = a; // от типа int к типу floatSystem.out.println(b); // 2.14748365E9 |
Явные преобразования
Во всех остальных преобразованиях примитивных типов явным образом применяется операция преобразования типов. Обычно это сужающие преобразования (narrowing) от типа с большей разрядностью к типу с меньшей разрядностью:
1 2 | long a = 4;int b = (int) a; |
Потеря данных при преобразовании
При применении явных преобразований мы можем столкнуться с потерей данных. Например, в следующем коде у нас не возникнет никаких проблем:
1 2 3 | int a = 5;byte b = (byte) a;System.out.println(b); // 5 |
Число 5 вполне укладывается в диапазон значений типа byte, поэтому после преобразования переменная b будет равна 5. Но что будет в следующем случае:
1 2 3 | int a = 258;byte b = (byte) a;System.out.println(b); // 2 |
Результатом будет число 2. В данном случае число 258 вне диапазона для типа byte (от -128 до 127), поэтому произойдет усечение значения. Почему результатом будет именно число 2?
Число a, которое равно 258, в двоичном системе будет равно 00000000 00000000 00000001 00000010.
Значения типа byte занимают в памяти только 8 бит. Поэтому двоичное представление числа int усекается до 8 правых разрядов, то есть 00000010,
что в десятичной системе дает число 2.
Усечение рациональных чисел до целых
При преобразовании значений с плавающей точкой к целочисленным значениям, происходит усечение дробной части:
1 2 | double a = 56.9898;int b = (int)a; |
Здесь значение числа b будет равно 56, несмотря на то, что число 57 было бы ближе к 56.9898. Чтобы избежать подобных казусов, надо применять функцию округления, которая есть в математической библиотеке Java:
1 2 | double a = 56.9898;int b = (int)Math.round(a); |
Преобразования при операциях
Нередки ситуации, когда приходится применять различные операции, например, сложение и произведение, над значениями разных типов. Здесь также действуют некоторые правила:
если один из операндов операции относится к типу
double, то и второй операнд преобразуется к типуdoubleесли предыдущее условие не соблюдено, а один из операндов операции относится к типу
float, то и второй операнд преобразуется к типуfloatесли предыдущие условия не соблюдены, один из операндов операции относится к типу
long, то и второй операнд преобразуется к типуlongиначе все операнды операции преобразуются к типу
int
Примеры преобразований:
1 2 3 | int a = 3;double b = 4.6;double c = a+b; |
Так как в операции участвует значение типа double, то и другое значение приводится к типу double и сумма двух значений a+b будет
представлять тип double.
Другой пример:
1 2 3 | byte a = 3;short b = 4;byte c = (byte)(a+b); |
Две переменных типа byte и short (не double, float или long), поэтому при сложении они преобразуются к типу int, и их сумма
a+b представляет значение типа int. Поэтому если затем мы присваиваем эту сумму переменной типа byte, то нам опять надо сделать
преобразование типов к byte.
Если в операциях участвуют данные типа char, то они преобразуются в int:
1 2 | int d = 'a' + 5;System.out.println(d); // 102 |
Одним из фундаментальных элементов многих языков программирования являются условные конструкции. Данные конструкции позволяют направить работу программы по одному из путей в зависимости от определенных условий.
В языке Java используются следующие условные конструкции: if..else и switch..case
Конструкция if/else
Выражение if/else проверяет истинность некоторого условия и в зависимости от результатов проверки выполняет определенный код:
1 2 3 4 5 | int num1 = 6;int num2 = 4;if(num1>num2){ System.out.println("Первое число больше второго");} |
После ключевого слова if ставится условие. И если это условие выполняется, то срабатывает код, который помещен в далее в
блоке if после фигурных скобок. В качестве условий выступает операция сравнения двух чисел.
Так как, в данном случае первое число больше второго, то выражение num1 > num2 истинно и возвращает значение
true. Следовательно, управление переходит в блок кода после фигурных скобок и начинает выполнять содержащиеся там инструкции, а
конкретно метод System.out.println("Первое число больше второго");. Если бы первое число оказалось бы меньше второго или равно ему, то инструкции в блоке if не выполнялись бы.
Но что, если мы захотим, чтобы при несоблюдении условия также выполнялись какие-либо действия? В этом случае мы можем добавить блок else:
1 2 3 4 5 6 7 8 | int num1 = 6;int num2 = 4;if(num1>num2){ System.out.println("Первое число больше второго");}else{ System.out.println("Первое число меньше второго");} |
Но при сравнении чисел мы можем насчитать три состояния: первое число больше второго, первое число меньше второго и числа равны.
С помощью выражения else if, мы можем обрабатывать дополнительные условия:
1 2 3 4 5 6 7 8 9 10 11 | int num1 = 6;int num2 = 8;if(num1>num2){ System.out.println("Первое число больше второго");}else if(num1<num2){ System.out.println("Первое число меньше второго");}else{ System.out.println("Числа равны");} |
Также мы можем соединить сразу несколько условий, используя логические операторы:
1 2 3 4 5 | int num1 = 8;int num2 = 6;if(num1 > num2 && num1>7){ System.out.println("Первое число больше второго и больше 7");} |
Здесь блок if будет выполняться, если num1 > num2 равно true и одновременно num1>7 равно true.
Конструкция switch
Конструкция switch/case аналогична конструкции if/else, так как позволяет обработать сразу несколько условий:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | int num = 8;switch(num){ case 1: System.out.println("число равно 1"); break; case 8: System.out.println("число равно 8"); num++; break; case 9: System.out.println("число равно 9"); break; default: System.out.println("число не равно 1, 8, 9");} |
После ключевого слова switch в скобках идет сравниваемое выражение. Значение этого выражения последовательно сравнивается со значениями, помещенными после операторов сase. И если совпадение найдено, то будет выполняет соответствующий блок сase.
В конце блока сase ставится оператор break, чтобы избежать выполнения других блоков. Например, если бы убрали оператор break в следующем случае:
1 2 3 4 5 6 | case 8: System.out.println("число равно 8"); num++;case 9: System.out.println("число равно 9"); break; |
то выполнился бы блок case 8, (поскольку переменная num равна 8). Но так как в этом блоке оператор break отсутствует, то начал бы выполняться блок case 9.
Если мы хотим также обработать ситуацию, когда совпадения не будет найдено, то можно добавить блок default, как в примере выше. Хотя блок default необязателен.
Также мы можем определить одно действие сразу для нескольких блоков case подряд:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 | int num = 3;int output = 0;switch(num){ case 1: output = 3; break; case 2: case 3: case 4: output = 6; break; case 5: output = 12; break; default: output = 24;}System.out.println(output); |
Тернарная операция
Тернарную операция имеет следующий синтаксис: [первый операнд - условие] ? [второй операнд] : [третий операнд].
Таким образом, в этой операции участвуют сразу три операнда.
В зависимости от условия тернарная операция возвращает второй или третий операнд: если условие равно true, то
возвращается второй операнд; если условие равно false, то третий. Например:
1 2 3 4 | int x=3;int y=2;int z = x<y? (x+y) : (x-y);System.out.println(z); |
Здесь результатом тернарной операции является переменная z. Сначала проверяется условие x<y.
И если оно соблюдается, то z будет равно второму операнду - (x+y), иначе z будет равно третьему операнду.
Еще одним видом управляющих конструкций являются циклы. Циклы позволяют в зависимости от определенных условий выполнять определенное действие множество раз. В языке Java есть следующие виды циклов:
for
while
do...while
Цикл for
Цикл for имеет следующее формальное определение:
1 2 3 4 | for ([инициализация счетчика]; [условие]; [изменение счетчика]){ // действия} |
Рассмотрим стандартный цикл for:
1 2 3 | for (int i = 1; i < 9; i++){ System.out.printf("Квадрат числа %d равен %d \n", i, i * i);} |
Первая часть объявления цикла - int i = 1 создает и инициализирует счетчик i. Счетчик необязательно должен представлять тип
int. Это может быть и любой другой числовой тип, например, float. Перед выполнением цикла значение счетчика будет равно 1. В данном
случае это то же самое, что и объявление переменной.
Вторая часть - условие, при котором будет выполняться цикл. В данном случае цикл будет выполняться, пока i не достигнет 9.
И третья часть - приращение счетчика на единицу. Опять же нам необязательно увеличивать на единицу. Можно уменьшать: i--.
В итоге блок цикла сработает 8 раз, пока значение i не станет равным 9. И каждый раз это значение будет увеличиваться на 1.
Нам необязательно указывать все условия при объявлении цикла. Например, мы можем написать так:
1 2 3 4 | int i = 1;for (; ;){ System.out.printf("Квадрат числа %d равен %d \n", i, i * i);} |
Определение цикла осталось тем же, только теперь блоки в определении у нас пустые: for (; ;). Теперь нет
инициализированной переменной-счетчика, нет условия, поэтому цикл будет работать вечно - бесконечный цикл.
Либо можно опустить ряд блоков:
1 2 3 4 5 | int i = 1;for (; i<9;){ System.out.printf("Квадрат числа %d равен %d \n", i, i * i); i++;} |
Этот пример эквивалентен первому примеру: у нас также есть счетчик, только создан он вне цикла. У нас есть условие выполнения цикла. И есть приращение счетчика уже в самом блоке for.
Цикл for может определять сразу несколько переменных и управлять ими:
1 2 3 4 5 | int n = 10;for(int i=0, j = n - 1; i < j; i++, j--){ System.out.println(i * j);} |
Цикл do
Цикл do сначала выполняет код цикла, а потом проверяет условие в инструкции while. И пока это условие истинно, цикл повторяется. Например:
1 2 3 4 5 6 | int j = 7;do{ System.out.println(j); j--;}while (j > 0); |
В данном случае код цикла сработает 7 раз, пока j не окажется равным нулю. Важно отметить, что цикл do гарантирует хотя бы однократное выполнение действий, даже если условие в инструкции while не будет истинно. Так, мы можем написать:
1 2 3 4 5 6 | int j = -1;do{ System.out.println(j); j--;}while (j > 0); |
Хотя переменная j изначально меньше 0, цикл все равно один раз выполнится.
Цикл while
Цикл while сразу проверяет истинность некоторого условия, и если условие истинно, то код цикла выполняется:
1 2 3 4 5 6 | int j = 6;while (j > 0){ System.out.println(j); j--;} |
Операторы continue и break
Оператор break позволяет выйти из цикла в любой его момент, даже если цикл не закончил свою работу:
Например:
1 2 3 4 5 | for (int i = 0; i < 10; i++){ if (i == 5) break; System.out.println(i);} |
Когда счетчик станет равным 5, сработает оператор break, и цикл завершится.
Теперь сделаем так, чтобы если число равно 5, цикл не завершался, а просто переходил к следующей итерации. Для этого используем оператор continue:
1 2 3 4 5 | for (int i = 0; i < 10; i++){ if (i == 5) continue; System.out.println(i);} |
В этом случае, когда выполнение цикла дойдет до числа 5, программа просто пропустит это число и перейдет к следующему.
Массив представляет набор однотипных значений. Объявление массива похоже на объявление обычной переменной, которая хранит одиночное значение, причем есть два способа объявления массива:
1 2 3 | тип_данных название_массива[];// либотип_данных[] название_массива; |
Например, определим массив чисел:
1 2 | int nums[];int[] nums2; |
После объявления массива мы можем инициализовать его:
1 2 | int nums[];nums = new int[4]; // массив из 4 чисел |
Создание массива производится с помощью следующей конструкции: new тип_данных[количество_элементов], где new - ключевое слово,
выделяющее память для указанного в скобках количества элементов. Например, nums = new int[4]; - в этом выражении создается массив
из четырех элементов int, и каждый элемент будет иметь значение по умолчанию - число 0.
Также можно сразу при объявлении массива инициализировать его:
1 2 | int nums[] = new int[4]; // массив из 4 чиселint[] nums2 = new int[5]; // массив из 5 чисел |
При подобной инициализации все элементы массива имеют значение по умолчанию. Для числовых типов (в том числе для типа char) это число 0, для типа boolean это
значение false, а для остальных объектов это значение null. Например, для типа int значением по умолчанию является число 0, поэтому выше
определенный массив nums будет состоять из четырех нулей.
Однако также можно задать конкретные значения для элементов массива при его создании:
1 2 3 4 | // эти два способа равноценныint[] nums = new int[] { 1, 2, 3, 5 };int[] nums2 = { 1, 2, 3, 5 }; |
Стоит отметить, что в этом случае в квадратных скобках не указывается размер массива, так как он вычисляется по количеству элементов в фигурных скобках.
После создания массива мы можем обратиться к любому его элементу по индексу, который передается в квадратных скобках после названия переменной массива:
1 2 3 4 5 6 7 8 9 | int[] nums = new int[4];// устанавливаем значения элементов массиваnums[0] = 1;nums[1] = 2;nums[2] = 4;nums[3] = 100; // получаем значение третьего элемента массиваSystem.out.println(nums[2]); // 4 |
Индексация элементов массива начинается с 0, поэтому в данном случае, чтобы обратиться к четвертому элементу в массиве, нам надо использовать
выражение nums[3].
И так как у нас массив определен только для 4 элементов, то мы не можем обратиться, например, к шестому элементу: nums[5] = 5;.
Если мы так попытаемся сделать, то мы получим ошибку.
Длина массива
Важнейшее свойство, которым обладают массивы, является свойство length, возвращающее длину массива, то есть количество его элементов:
1 2 | int[] nums = {1, 2, 3, 4, 5};int length = nums.length; // 5 |
Нередко бывает неизвестным последний индекс, и чтобы получить последний элемент массива, мы можем использовать это свойство:
1 | int last = nums[nums.length-1]; |
Многомерные массивы
Ранее мы рассматривали одномерные массивы, которые можно представить как цепочку или строку однотипных значений. Но кроме одномерных массивов также бывают и многомерными. Наиболее известный многомерный массив - таблица, представляющая двухмерный массив:
1 2 3 | int[] nums1 = new int[] { 0, 1, 2, 3, 4, 5 };int[][] nums2 = { { 0, 1, 2 }, { 3, 4, 5 } }; |
Визуально оба массива можно представить следующим образом:
Одномерный массив nums1
0 | 1 | 2 | 3 | 4 | 5 |
Двухмерный массив nums2
0 | 1 | 2 |
3 | 4 | 5 |
Поскольку массив nums2 двухмерный, он представляет собой простую таблицу. Его также можно было создать следующим образом:
int[][] nums2 = new int[2][3];. Количество квадратных скобок указывает на размерность массива. А числа в скобках - на количество
строк и столбцов. И также, используя индексы, мы можем использовать элементы массива в программе:
1 2 3 | // установим элемент первого столбца второй строкиnums2[1][0]=44;System.out.println(nums2[1][0]); |
Объявление трехмерного массива могло бы выглядеть так:
1 | int[][][] nums3 = new int[2][3][4]; |
Зубчатый массив
Многомерные массивы могут быть также представлены как "зубчатые массивы". В вышеприведенном примере двухмерный массив имел 2 строчки и три столбца, поэтому у нас получалась ровная таблица. Но мы можем каждому элементу в двухмерном массиве присвоить отдельный массив с различным количеством элементов:
1 2 3 4 | int[][] nums = new int[3][];nums[0] = new int[2];nums[1] = new int[3];nums[2] = new int[5]; |
foreach
Специальная версия цикла for предназначена для перебора элементов в наборах элементов, например, в массивах и коллекциях.
Она аналогична действию цикла foreach , который имеется в других языках программирования. Формальное ее объявление:
1 2 3 | for (тип_данных название_переменной : контейнер){ // действия} |
Например:
1 2 3 4 5 | int[] array = new int[] { 1, 2, 3, 4, 5 };for (int i : array){ System.out.println(i);} |
В качестве контейнера в данном случае выступает массив данных типа int. Затем объявляется переменная с типом int
То же самое можно было бы сделать и с помощью обычной версии for:
1 2 3 4 | int[] array = new int[] { 1, 2, 3, 4, 5 };for (int i = 0; i < array.length; i++){ System.out.println(array[i]);} |
В то же время эта версия цикла for более гибкая по сравнению for (int i : array). В частности, в этой версии мы можем изменять элементы:
1 2 3 4 5 | int[] array = new int[] { 1, 2, 3, 4, 5 };for (int i=0; i<array.length;i++){ array[i] = array[i] * 2; System.out.println(array[i]);} |
Перебор многомерных массивов в цикле
1 2 3 4 5 6 7 8 9 10 11 12 13 | int[][] nums = new int[][] { {1, 2, 3}, {4, 5, 6}, {7, 8, 9}};for (int i = 0; i < nums.length; i++){ for(int j=0; j < nums[i].length; j++){ System.out.printf("%d ", nums[i][j]); } System.out.println();} |
Сначала создается цикл для перебора по строкам, а затем внутри первого цикла создается внутренний цикл для перебора по столбцам конкретной строки. Подобным образом можно перебрать и трехмерные массивы и наборы с большим количеством размерностей.
Если переменные и константы хранят некоторые значения, то методы содержат собой набор операторов, которые выполняют определенные действия.
Общее определение методов выглядит следующим образом:
1 2 3 | [модификаторы] тип_возвращаемого_значения название_метода ([параметры]){ // тело метода} |
Модификаторы и параметры необязательны.
По умолчанию главный класс любой программы на Java содержит метод main, который служит точкой входа в программу:
1 2 3 | public static void main(String[] args) { System.out.println("привет мир!");} |
Ключевые слова public и static являются модификаторами. Далее идет тип возвращаемого значения.
Ключевое слово void указывает на то, что метод ничего не возвращает.
Затем идут название метода - main и в скобках параметры метода - String[] args. И в фигурные скобки заключено тело метода - все действия,
которые он выполняет.
Создадим еще несколько методов:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | public class Program{ public static void main (String args[]){ } void hello(){ System.out.println("Hello"); } void welcome(){ System.out.println("Welcome to Java 10"); }} |
Здесь определены два дополнительных метода: hello и welcome, каждый из которых выводит некоторую строку на консоль. Методы определяются внутри класса - в данном случае внутри класса Program, в котором определен метод main.
Но если мы скомпилируем и запустим данную программу, то мы ничего не увидим на консоли. В примере выше мы определили два метода, но мы их нигде не вызываем. По умолчанию в программе Java выполняется только метод main и все его содержимое. Поэтому, если мы хотим, чтобы другие методы тоже выполнялись, их надо вызвать в методе main.
Вызов метода осуществляется в форме:
1 | имя_метода(аргументы); |
После имени метода указываются скобки, в которых перечисляются аргументы - значения для параметров метода.
Например, определим и выполним несколько методов:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | public class Program{ public static void main (String args[]){ hello(); welcome(); welcome(); } static void hello(){ System.out.println("Hello"); } static void welcome(){ System.out.println("Welcome to Java 10"); }} |
В методе main вызывается один раз метод hello и два раза метод welcome. В этом и заключается одно из преимуществ методов: мы можем вынести некоторые общие действия в отдельный метод и затем вызывать многократно их в различных местах программы. Поскольку оба метода не имеют никаких параметров, то после их названия при вызове ставятся пустые скобки.
Также следует отметить, что чтобы вызвать в методе main другие методы, которые определены в одном классе с методом main, они должны иметь модификатор
static.
В итоге после компиляции и выполнения программы мы увидим на консоли:
Hello Welcome to Java 10 Welcome to Java 10
С помощью параметров мы можем передать в методы различные данные, которые будут использоваться для вычислений. Например:
1 2 3 4 5 | static void sum(int x, int y){ int z = x + y; System.out.println(z);} |
Данная функция принимает два параметра - два числа, складывает их и выводит их сумму на консоль.
А при вызове этого метода в программе нам необходимо передать на место параметров значения, которые соответствуют типу параметра:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | public class Program{ public static void main (String args[]){ int a = 6; int b = 8; sum(a, b); // 14 sum(3, a); // 9 sum(5, 23); // 28 } static void sum(int x, int y){ int z = x + y; System.out.println(z); }} |
Поскольку метод sum принимает два значения типа int, то на место параметров надо передать два значения типа int. Это могут быть и числовые литералы, и переменные типов данных, которые представляют тип int или могут быть автоматически преобразованы в тип int. Значения, которые передаются на место параметров, еще называются аргументами. Значения передаются параметрам по позиции, то есть первый аргумент первому параметру, второй аргумент - второму параметру и так далее.
Рассмотрим другой пример:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | public class Program{ public static void main (String args[]){ display("Tom", 34); display("Bob", 28); display("Sam", 23); } static void display(String name, int age){ System.out.println(name); System.out.println(age); }} |
Метод display принимает два параметра. Первый параметр представляет тип String, а второй - тип int. Поэтому при вызове метода вначале в него надо передать строку, а затем число.
Параметры переменной длины
Метод может принимать параметры переменной длины одного типа. Например, нам надо передать в метод набор числел и вычислить их сумму, но мы точно не знаем, сколько именно чисел будет передано - 3, 4, 5 или больше. Параметры переменной длины позволяют решить эту задачу:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | public class Program{ public static void main (String args[]){ sum(1, 2, 3); // 6 sum(1, 2, 3, 4, 5); // 15 sum(); // 0 } static void sum(int ...nums){ int result =0; for(int n: nums) result += n; System.out.println(result); }} |
Троеточие перед названием параметра int ...nums указывает на то, что он будет необязательным и будет представлять массив. Мы можем передать в метод sum
одно число, несколько чисел, а можем вообще не передавать никаких параметров. Причем, если мы хотим передать несколько параметров, то необязательный параметр должен указываться в конце:
1 2 3 4 5 6 7 8 9 10 11 12 13 | public static void main(String[] args) { sum("Welcome!", 20,10); sum("Hello World!");}static void sum(String message, int ...nums){ System.out.println(message); int result =0; for(int x:nums) result+=x; System.out.println(result);} |
Методы могут возвращать некоторое значение. Для этого применяется оператор return.
1 | return возвращаемое_значение; |
После оператора return указывается возвращаемое значение, которое является результатом метода. Это может быть литеральное значение, значение переменной или какого-то сложного выражения.
Например:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | public class Program{ public static void main (String args[]){ int x = sum(1, 2, 3); int y = sum(1, 4, 9); System.out.println(x); // 6 System.out.println(y); // 14 } static int sum(int a, int b, int c){ return a + b + c; }} |
В методе в качестве типа возвращаемого значения вместо void используется любой другой тип. В данном случае метод sum возвращает значение типа
int, поэтому этот тип указывается перед названием метода. Причем если в качестве возвращаемого типа для метода определен любой
другой, отличный от void, то метод обязательно должен использовать оператор return для возвращения значения.
При этом возвращаемое значение всегда должно иметь тот же тип, что значится в определении функции. И если функция
возвращает значение типа int, то после оператора return стоит целочисленное значение,
которое является объектом типа int. Как в данном случае это сумма значений параметров метода.
Метод может использовать несколько вызовов оператора return для возваращения разных значений в зависимости от некоторых условий:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 | public class Program{ public static void main (String args[]){ System.out.println(daytime(7)); // Good morning System.out.println(daytime(13)); // Good after noon System.out.println(daytime(18)); // Good evening System.out.println(daytime(2)); // Good night } static String daytime(int hour){ if (hour >24 || hour < 0) return "Invalid data"; else if(hour > 21 || hour < 6) return "Good night"; else if(hour >= 15) return "Good evening"; else if(hour >= 11) return "Good after noon"; else return "Good morning"; }} |
Здесь метод daytime возвращает значение типа String, то есть строку, и в зависимости от значения параметра hour возвращаемая строка будет различаться.
Выход из метода
Оператор return применяется для возвращаения значения из метода, но и для выхода из метода. В подобном качестве оператор return применяется в методах, которые ничего не возвращают,
то есть имеют тип void:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 | public class Program{ public static void main (String args[]){ daytime(7); // Good morning daytime(13); // Good after noon daytime(32); // daytime(56); // daytime(2); // Good night } static void daytime(int hour){ if (hour >24 || hour < 0) return; if(hour > 21 || hour < 6) System.out.println("Good night"); else if(hour >= 15) System.out.println("Good evening"); else if(hour >= 11) System.out.println("Good after noon"); else System.out.println("Good morning"); }} |
Если переданное в метод datetime значение больше 24 или меньше 0, то просто выходим из метода. Возвращаемое значение после return указывать в этом случае не нужно.
В программе мы можем использовать методы с одним и тем же именем, но с разными типами и/или количеством параметров. Такой механизм называется перегрузкой методов (method overloading).
Например:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 | public class Program{ public static void main(String[] args) { System.out.println(sum(2, 3)); // 5 System.out.println(sum(4.5, 3.2)); // 7.7 System.out.println(sum(4, 3, 7)); // 14 } static int sum(int x, int y){ return x + y; } static double sum(double x, double y){ return x + y; } static int sum(int x, int y, int z){ return x + y + z; }} |
Здесь определено три варианта или три перегрузки метода sum(), но при его вызове в зависимости от типа и количества передаваемых
параметров система выберет именно ту версию, которая наиболее подходит.
Стоит отметить, что на перегрузку методов влияют количество и типы параметров. Однако различие в типе возвращаемого значения для перегрузки не имеют никакого значения. Например, в следующем случае методы различаются по типу возвращаемого значения:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | public class Program{ public static void main(String[] args) { System.out.println(sum(2, 3)); System.out.println(sum(4, 3)); } static int sum(int x, int y){ return x + y; } static double sum(int x, int y){ return x + y; }} |
Однако перегрузкой это не будет считаться. Более того такая программа некорректна и попросту не скомилируется, так как метод с одним и тем же количеством и типом параметров определен несколько раз.
Отдельно рассмотрим рекурсивные функции. Главное отличие рекурсивных функций от обычных методов состоит в том, что они рекурсивная функция может вызывать саму себя.
Например, рассмотрим функцию, которая вычисляет факториал числа:
1 2 3 4 5 6 7 8 | static int factorial(int x){ if (x == 1){ return 1; } return x * factorial(x - 1);} |
Вначале проверяется условие: если вводимое число не равно 1, то мы умножаем данное число на результат этой же функции, в которую в качестве параметра передается число x-1. То есть происходит рекурсивный спуск. И так дальше, пока не дойдем того момента, когда значение параметра не будет равно единице.
Рекурсивная функция обязательно должна иметь некоторый базовый вариант, который использует оператор return и который помещается в начале функции.
В случае с факториалом это if (x == 1) return 1;. И все рекурсивные вызовы должны обращаться к подфункциям, которые в конечном счете
сходятся к базовому варианту. Так, при передаче в функцию положительного числа при дальнейших рекурсивных вызовах подфункций в них будет передаваться
каждый раз число, меньшее на единицу. И в конце концов мы дойдем до ситуации, когда число будет равно 1, и будет использован базовый вариант.
Хотя в данном случае нужно отметить, что для определения факториала есть более оптимальные решения на основе циклов:
1 2 3 4 5 6 7 8 | static int factorial(int x){ int result=1; for (int i = 1; i <= x; i++) { result *= i; } return result;} |
Еще одним распространенным примером рекурсивной функции служит функция, вычисляющая числа Фибоначчи. В теории n-й член последовательности Фибоначчи определяется по формуле: f(n)=f(n-1) + f(n-2), причем f(0)=0, а f(1)=1.
1 2 3 4 5 6 7 8 9 10 11 12 | static int fibonachi(int n){ if (n == 0){ return 0; } if (n == 1){ return 1; } else{ return fibonachi(n - 1) + fibonachi(n - 2); }} |
Нередко в процессе выполнения программы могут возникать ошибки, при том необязательно по вине разработчика. Некоторые из них трудно предусмотреть или предвидеть, а иногда и вовсе невозможно. Так, например, может неожиданно оборваться сетевое подключение при передаче файла. Подобные ситуации называются исключениями.
В языке Java предусмотрены специальные средства для обработки подобных ситуаций. Одним из таких средств является конструкция try...catch...finally. При возникновении исключения в блоке try управление переходит в блок catch, который может обработать данное исключение. Если такого блока не найдено, то пользователю отображается сообщение о необработанном исключении, а дальнейшее выполнение программы останавливается. И чтобы подобной остановки не произошло, и надо использовать блок try..catch. Например:
1 2 3 | int[] numbers = new int[3];numbers[4]=45;System.out.println(numbers[4]); |
Так как у нас массив numbers может содержать только 3 элемента, то при выполнении инструкции numbers[4]=45 консоль отобразит
исключение, и выполнение программы будет завершено. Теперь попробуем обработать это исключение:
1 2 3 4 5 6 7 8 9 10 | try{ int[] numbers = new int[3]; numbers[4]=45; System.out.println(numbers[4]);}catch(Exception ex){ ex.printStackTrace();}System.out.println("Программа завершена"); |
При использовании блока try...catch вначале выполняются все инструкции между операторами try и catch.
Если в блоке try вдруг возникает исключение, то обычный порядок выполнения останавливается и переходит к инструкции сatch.
Поэтому когда выполнение программы дойдет до строки numbers[4]=45;, программа остановится и перейдет к блоку catch
Выражение catch имеет следующий синтаксис: catch (тип_исключения имя_переменной).
В данном случае объявляется переменная ex, которая имеет тип Exception. Но если возникшее исключение не
является исключением типа, указанного в инструкции сatch, то оно не обрабатывается, а программа просто зависает или выбрасывает
сообщение об ошибке.
Но так как тип Exception является базовым классом для всех исключений, то выражение catch (Exception ex)
будет обрабатывать практически все исключения. Обработка же исключения в данном случае сводится к выводу на консоль стека трассировки ошибки с
помощью метода printStackTrace(), определенного в классе Exception.
После завершения выполнения блока catch программа продолжает свою работу, выполняя все остальные инструкции после блока catch.
Конструкция try..catch также может иметь блок finally. Однако этот блок необязательный, и его можно при обработке исключений
опускать. Блок finally выполняется в любом случае, возникло ли исключение в блоке try или нет:
1 2 3 4 5 6 7 8 9 10 11 12 13 | try{ int[] numbers = new int[3]; numbers[4]=45; System.out.println(numbers[4]);}catch(Exception ex){ ex.printStackTrace();}finally{ System.out.println("Блок finally");}System.out.println("Программа завершена"); |
Обработка нескольких исключений
В Java имеется множество различных типов исключений, и мы можем разграничить их обработку, включив дополнительные блоки catch:
1 2 3 4 5 6 7 8 9 10 11 12 13 | int[] numbers = new int[3];try{ numbers[6]=45; numbers[6]=Integer.parseInt("gfd");}catch(ArrayIndexOutOfBoundsException ex){ System.out.println("Выход за пределы массива");}catch(NumberFormatException ex){ System.out.println("Ошибка преобразования из строки в число");} |
Если у нас возникает исключение определенного типа, то оно переходит к соответствующему блоку catch.
Оператор throw
Чтобы сообщить о выполнении исключительных ситуаций в программе, можно использовать оператор throw. То есть с помощью этого оператора мы сами можем создать исключение и вызвать его в процессе выполнения. Например, в нашей программе происходит ввод числа, и мы хотим, чтобы, если число больше 30, то возникало исключение:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 | package firstapp;import java.util.Scanner;public class FirstApp { public static void main(String[] args) { try{ Scanner in = new Scanner(System.in); int x = in.nextInt(); if(x>=30){ throw new Exception("Число х должно быть меньше 30"); } } catch(Exception ex){ System.out.println(ex.getMessage()); } System.out.println("Программа завершена"); } } |
Здесь для создания объекта исключения используется конструктор класса Exception, в который передается сообщение об исключении. И если число х окажется больше 29, то будет выброшено исключение и управление перейдет к блоку catch.
В блоке catch мы можем получить сообщение об исключении с помощью метода getMessage().
Основы программирования на Java
1. ПЕРЕМЕННЫЕ И КОНСТАНТЫ
Базовые задачи:
Определить переменные: Создайте переменные для хранения имени, возраста и веса пользователя.
- Входные данные: имя = "Алексей", возраст = 25, вес = 70.
- Решение:java
String name = "Алексей"; int age = 25; double weight = 70.0;
Константы: Определите константу для числа Пи и выведите её на экран.
- Входные данные: Пи = 3.14.
- Решение:java
final double PI = 3.14; System.out.println(PI);
Изменение переменной: Измените значение переменной возраста на 1 год.
- Входные данные: возраст = 25.
- Решение:java
age++;
Обмен значениями: Обменяйте значения двух переменных.
- Входные данные: a = 5, b = 10.
- Решение:java
int a = 5, b = 10; int temp = a; a = b; b = temp;
Типы переменных: Определите переменные разных типов и выведите их значения.
- Входные данные: int num = 10, double d = 3.5, char c = 'A'.
- Решение:java
int num = 10; double d = 3.5; char c = 'A'; System.out.println(num + " " + d + " " + c);
Сравнение переменных: Сравните два числа и выведите большее.
- Входные данные: a = 10, b = 20.
- Решение:java
int a = 10, b = 20; int max = (a > b) ? a : b; System.out.println(max);
Сложение переменных: Сложите два целых числа и выведите результат.
- Входные данные: a = 10, b = 20.
- Решение:java
int sum = a + b; System.out.println(sum);
Проверка на четность: Проверьте, является ли число четным.
- Входные данные: num = 4.
- Решение:java
if (num % 2 == 0) { System.out.println(num + " четное"); }
Кратное число: Проверьте, кратно ли число 5.
- Входные данные: num = 15.
- Решение:java
if (num % 5 == 0) { System.out.println(num + " кратно 5"); }
Переменные строк: Объедините две строки.
- Входные данные: String first = "Hello", second = "World".
- Решение:java
String combined = first + " " + second; System.out.println(combined);
Сложные задачи:
Конвертация температур: Напишите программу, которая конвертирует температуру из Цельсия в Фаренгейт.
- Входные данные: температураЦельсия = 100.
- Решение:java
double celsius = 100; double fahrenheit = (celsius * 9/5) + 32; System.out.println(fahrenheit);
Квадрат числа: Напишите программу, которая принимает число и выводит его квадрат.
- Входные данные: num = 6.
- Решение:java
int num = 6; System.out.println(num * num);
Площадь круга: Рассчитайте площадь круга по радиусу.
- Входные данные: радиус = 7.
- Решение:java
double radius = 7; double area = PI * radius * radius; System.out.println(area);
Периметр прямоугольника: Рассчитайте периметр прямоугольника.
- Входные данные: длина = 5, ширина = 10.
- Решение:java
int length = 5, width = 10; int perimeter = 2 * (length + width); System.out.println(perimeter);
Сумма чисел: Напишите программу, которая вычисляет сумму всех чисел от 1 до N.
- Входные данные: N = 10.
- Решение:java
int N = 10; int sum = (N * (N + 1)) / 2; System.out.println(sum);
Умножение двух чисел: Напишите программу для умножения двух чисел.
- Входные данные: a = 5, b = 6.
- Решение:java
int a = 5, b = 6; int product = a * b; System.out.println(product);
Сравнение строк: Напишите программу для сравнения двух строк.
- Входные данные: str1 = "Java", str2 = "Java".
- Решение:java
if (str1.equals(str2)) { System.out.println("Строки равны"); }
Свойства переменных: Определите, является ли переменная строкового типа пустой.
- Входные данные: String str = "".
- Решение:java
if (str.isEmpty()) { System.out.println("Строка пустая"); }
Максимальное из трех чисел: Напишите программу, которая находит максимальное из трех чисел.
- Входные данные: a = 5, b = 10, c = 7.
- Решение:java
int max = Math.max(a, Math.max(b, c)); System.out.println(max);
Числовая последовательность: Выведите первую N чисел Фибоначчи.
- Входные данные: N = 5.
- Решение:java
int n = 5, a = 0, b = 1; for (int i = 0; i < n; i++) { System.out.print(a + " "); int next = a + b; a = b; b = next; }
2. ТИПЫ ДАННЫХ
Базовые задачи:
Объявление и инициализация: Объявите переменные различных типов данных и выведите их на экран.
- Входные данные: int a = 10, double b = 5.5, char c = 'X'.
- Решение:java
int a = 10; double b = 5.5; char c = 'X'; System.out.println(a + " " + b + " " + c);
Конвертация типов: Преобразуйте целое число в строку.
- Входные данные: int num = 42.
- Решение:java
String str = String.valueOf(num); System.out.println(str);
Сложение разных типов: Сложите целое число и дробное.
- Входные данные: int a = 5, double b = 4.5.
- Решение:java
double sum = a + b; System.out.println(sum);
Проверка типа: Проверьте, является ли переменная целым числом.
- Входные данные: Object obj = 10.
- Решение:java
if (obj instanceof Integer) { System.out.println("Это целое число"); }
Объявление массива: Создайте массив целых чисел и выведите его длину.
- Входные данные: int[] arr = {1, 2, 3}.
- Решение:java
int[] arr = {1, 2, 3}; System.out.println(arr.length);
Кратное число: Создайте переменную и проверьте, является ли она кратной 3.
- Входные данные: int num = 9.
- Решение:java
if (num % 3 == 0) { System.out.println(num + " кратно 3"); }
Объявление строкового массива: Создайте массив строк и выведите его первый элемент.
- Входные данные: String[] names = {"Алексей", "Иван", "Света"}.
- Решение:java
String[] names = {"Алексей", "Иван", "Света"}; System.out.println(names[0]);
Сложение двух дробей: Создайте переменные для двух дробей и сложите их.
- Входные данные: double x = 1.5, y = 2.5.
- Решение:java
double sum = x + y; System.out.println(sum);
Проверка символа: Проверьте, является ли символ гласной буквой.
- Входные данные: char letter = 'A'.
- Решение:java
if ("AEIOUaeiou".indexOf(letter) != -1) { System.out.println(letter + " гласная буква"); }
Объединение строк: Объедините две строки в одну.
- Входные данные: String str1 = "Привет", str2 = "Мир".
- Решение:java
String combined = str1 + " " + str2; System.out.println(combined);
Сложные задачи:
Сложение дробей: Напишите программу для сложения двух дробных чисел.
- Входные данные: double a = 2.5, b = 3.75.
- Решение:java
double result = a + b; System.out.println(result);
Поиск максимального значения в массиве: Напишите программу, которая находит максимальное значение в массиве.
- Входные данные: int[] arr = {1, 3, 5, 7, 2}.
- Решение:java
int max = arr[0]; for (int num : arr) { if (num > max) { max = num; } } System.out.println(max);
Сравнение чисел с плавающей точкой: Сравните два дробных числа и выведите большее.
- Входные данные: double a = 5.3, b = 4.8.
- Решение:java
double max = Math.max(a, b); System.out.println(max);
Проверка целого числа: Напишите программу, которая проверяет, является ли строка целым числом.
- Входные данные: String str = "123".
- Решение:java
try { int num = Integer.parseInt(str); System.out.println(num + " это целое число"); } catch (NumberFormatException e) { System.out.println("Не целое число"); }
Нахождение среднеарифметического: Вычислите среднее арифметическое трех чисел.
- Входные данные: double a = 5, b = 10, c = 15.
- Решение:java
double average = (a + b + c) / 3; System.out.println(average);
Проверка на ноль: Напишите программу, которая проверяет, является ли число нулем.
- Входные данные: double number = 0.
- Решение:java
if (number == 0) { System.out.println("Число ноль"); }
Сравнение строк: Сравните две строки без учета регистра.
- Входные данные: String str1 = "java", str2 = "Java".
- Решение:java
if (str1.equalsIgnoreCase(str2)) { System.out.println("Строки равны"); }
Обработка строк: Найдите длину строки и выведите её.
- Входные данные: String str = "Hello, World!".
- Решение:java
int length = str.length(); System.out.println(length);
Изменение регистра: Измените строку на верхний регистр.
- Входные данные: String str = "hello".
- Решение:java
String upperStr = str.toUpperCase(); System.out.println(upperStr);
Подстрока: Извлеките подстроку из строки.
- Входные данные: String str = "Hello, World!".
- Решение:java
String substring = str.substring(0, 5); System.out.println(substring);
3. КОНСОЛЬНЫЙ ВВОД/ВЫВОД В JAVA
Базовые задачи:
Чтение имени: Напишите программу, которая запрашивает имя и выводит его.
- Входные данные: "Алексей".
- Решение:java
Scanner scanner = new Scanner(System.in); System.out.print("Введите имя: "); String name = scanner.nextLine(); System.out.println("Привет, " + name);
Чтение числа: Запросите у пользователя число и выведите его удвоенное значение.
- Входные данные: 4.
- Решение:java
System.out.print("Введите число: "); int num = scanner.nextInt(); System.out.println("Удвоенное число: " + (num * 2));
Чтение нескольких значений: Запросите у пользователя два числа и выведите их сумму.
- Входные данные: 5, 10.
- Решение:java
System.out.print("Введите два числа: "); int a = scanner.nextInt(); int b = scanner.nextInt(); System.out.println("Сумма: " + (a + b));
Чтение строки и числа: Запросите имя и возраст, затем выведите их.
- Входные данные: "Иван", 30.
- Решение:java
System.out.print("Введите имя: "); String name = scanner.nextLine(); System.out.print("Введите возраст: "); int age = scanner.nextInt(); System.out.println("Имя: " + name + ", Возраст: " + age);
Форматированный вывод: Напишите программу, которая выводит сообщение с использованием форматирования.
- Входные данные: name = "Света", age = 25.
- Решение:java
System.out.printf("Имя: %s, Возраст: %d\n", name, age);
Считывание символа: Запросите у пользователя символ и выведите его.
- Входные данные: 'A'.
- Решение:java
System.out.print("Введите символ: "); char c = scanner.next().charAt(0); System.out.println("Вы ввели: " + c);
Запрос нескольких строк: Запросите у пользователя три строки и выведите их.
- Входные данные: "Первый", "Второй", "Третий".
- Решение:java
String[] lines = new String[3]; for (int i = 0; i < 3; i++) { System.out.print("Введите строку " + (i + 1) + ": "); lines[i] = scanner.nextLine(); } System.out.println(Arrays.toString(lines));
Форматированный вывод: Выведите числа с плавающей точкой с двумя знаками после запятой.
- Входные данные: 5.678.
- Решение:java
System.out.printf("Число с двумя знаками: %.2f\n", num);
Считывание строки с пробелами: Запросите у пользователя строку с пробелами.
- Входные данные: "Привет мир!".
- Решение:java
System.out.print("Введите строку с пробелами: "); String str = scanner.nextLine(); System.out.println("Вы ввели: " + str);
Считывание массива: Запросите у пользователя 5 чисел и выведите их сумму.
- Входные данные: 1, 2, 3, 4, 5.
- Решение:java
int sum = 0; System.out.println("Введите 5 чисел: "); for (int i = 0; i < 5; i++) { sum += scanner.nextInt(); } System.out.println("Сумма: " + sum);
Сложные задачи:
Чтение данных о пользователе: Создайте программу, которая запрашивает данные о пользователе (имя, возраст, вес) и выводит их.
- Входные данные: "Света", 30, 55.5.
- Решение:java
System.out.print("Введите имя: "); String name = scanner.nextLine(); System.out.print("Введите возраст: "); int age = scanner.nextInt(); System.out.print("Введите вес: "); double weight = scanner.nextDouble(); System.out.printf("Имя: %s, Возраст: %d, Вес: %.2f\n", name, age, weight);
Считывание значений с использованием массива: Напишите программу, которая считывает 5 значений в массив и выводит их.
- Входные данные: 1, 2, 3, 4, 5.
- Решение:java
int[] numbers = new int[5]; for (int i = 0; i < numbers.length; i++) { System.out.print("Введите число " + (i + 1) + ": "); numbers[i] = scanner.nextInt(); } System.out.println("Вы ввели: " + Arrays.toString(numbers));
Вывод данных в табличном виде: Напишите программу, которая выводит данные в виде таблицы.
- Входные данные: "Имя", "Возраст".
- Решение:java
System.out.printf("%-10s %-10s\n", "Имя", "Возраст"); System.out.printf("%-10s %-10d\n", "Алексей", 25); System.out.printf("%-10s %-10d\n", "Иван", 30);
Считывание данных с проверкой: Напишите программу, которая запрашивает число до тех пор, пока не будет введено корректное значение.
- Входные данные: "abc", 10.
- Решение:java
int num; while (true) { System.out.print("Введите число: "); if (scanner.hasNextInt()) { num = scanner.nextInt(); break; } else { System.out.println("Некорректный ввод. Попробуйте снова."); scanner.next(); // очистка некорректного ввода } } System.out.println("Вы ввели: " + num);
Обработка ввода через массив: Запросите у пользователя 5 значений, а затем вычислите их среднее.
- Входные данные: 1, 2, 3, 4, 5.
- Решение:java
int[] numbers = new int[5]; int sum = 0; for (int i = 0; i < numbers.length; i++) { System.out.print("Введите число " + (i + 1) + ": "); numbers[i] = scanner.nextInt(); sum += numbers[i]; } double average = (double) sum / numbers.length; System.out.println("Среднее: " + average);
Запись результатов в файл: Напишите программу, которая сохраняет введенные числа в текстовый файл.
- Входные данные: 1, 2, 3.
- Решение:java
try (PrintWriter writer = new PrintWriter(new File("numbers.txt"))) { for (int i = 0; i < 3; i++) { System.out.print("Введите число " + (i + 1) + ": "); int num = scanner.nextInt(); writer.println(num); } } catch (FileNotFoundException e) { System.out.println("Файл не найден"); }
Ввод данных с использованием класса: Создайте класс User с полями имя и возраст, считывайте данные о пользователе и выводите их.
- Входные данные: "Света", 30.
- Решение:java
class User { String name; int age; } User user = new User(); System.out.print("Введите имя: "); user.name = scanner.nextLine(); System.out.print("Введите возраст: "); user.age = scanner.nextInt(); System.out.println("Имя: " + user.name + ", Возраст: " + user.age);
Чтение и вывод списка пользователей: Напишите программу, которая считывает данные о 3 пользователях и выводит их.
- Входные данные: (Света, 30), (Иван, 25), (Петя, 35).
- Решение:java
User[] users = new User[3]; for (int i = 0; i < 3; i++) { users[i] = new User(); System.out.print("Введите имя пользователя " + (i + 1) + ": "); users[i].name = scanner.nextLine(); System.out.print("Введите возраст пользователя " + (i + 1) + ": "); users[i].age = scanner.nextInt(); scanner.nextLine(); // очистка буфера } for (User user : users) { System.out.println("Имя: " + user.name + ", Возраст: " + user.age); }
Вывод чисел в порядке убывания: Запросите 5 чисел и выведите их в порядке убывания.
- Входные данные: 5, 3, 8, 1, 4.
- Решение:java
int[] numbers = new int[5]; for (int i = 0; i < 5; i++) { System.out.print("Введите число " + (i + 1) + ": "); numbers[i] = scanner.nextInt(); } Arrays.sort(numbers); for (int i = numbers.length - 1; i >= 0; i--) { System.out.print(numbers[i] + " "); }
Сохранение и чтение из файла: Напишите программу, которая записывает введенные числа в файл и затем считывает их обратно.
- Входные данные: 1, 2, 3.
- Решение:java
try (PrintWriter writer = new PrintWriter(new File("output.txt"))) { for (int i = 0; i < 3; i++) { System.out.print("Введите число " + (i + 1) + ": "); int num = scanner.nextInt(); writer.println(num); } } catch (FileNotFoundException e) { System.out.println("Файл не найден"); } try (Scanner fileScanner = new Scanner(new File("output.txt"))) { while (fileScanner.hasNextLine()) { System.out.println(fileScanner.nextLine()); } } catch (FileNotFoundException e) { System.out.println("Файл не найден"); }
4. АРИФМЕТИЧЕСКИЕ ОПЕРАЦИИ
Базовые задачи:
Сложение: Напишите программу, которая складывает два числа.
- Входные данные: a = 5, b = 10.
- Решение:java
int a = 5, b = 10; int sum = a + b; System.out.println("Сумма: " + sum);
Вычитание: Напишите программу, которая вычитает одно число из другого.
- Входные данные: a = 10, b = 5.
- Решение:java
int difference = a - b; System.out.println("Разность: " + difference);
Умножение: Напишите программу, которая умножает два числа.
- Входные данные: a = 4, b = 5.
- Решение:java
int product = a * b; System.out.println("Произведение: " + product);
Деление: Напишите программу, которая делит одно число на другое.
- Входные данные: a = 20, b = 5.
- Решение:java
int quotient = a / b; System.out.println("Частное: " + quotient);
Остаток от деления: Напишите программу, которая находит остаток от деления.
- Входные данные: a = 20, b = 3.
- Решение:java
int remainder = a % b; System.out.println("Остаток: " + remainder);
Возведение в степень: Напишите программу, которая возводит число в степень.
- Входные данные: base = 2, exponent = 3.
- Решение:java
double result = Math.pow(base, exponent); System.out.println("Результат: " + result);
Вычисление площади прямоугольника: Напишите программу, которая вычисляет площадь прямоугольника.
- Входные данные: width = 5, height = 10.
- Решение:java
int area = width * height; System.out.println("Площадь: " + area);
Вычисление периметра прямоугольника: Напишите программу, которая вычисляет периметр прямоугольника.
- Входные данные: width = 5, height = 10.
- Решение:java
int perimeter = 2 * (width + height); System.out.println("Периметр: " + perimeter);
Сравнение чисел: Напишите программу, которая сравнивает два числа и выводит большее.
- Входные данные: a = 5, b = 10.
- Решение:java
int max = Math.max(a, b); System.out.println("Большее число: " + max);
Квадрат числа: Напишите программу, которая вычисляет квадрат числа.
- Входные данные: x = 4.
- Решение:java
int square = x * x; System.out.println("Квадрат: " + square);
Сложные задачи:
Сложение дробных чисел: Напишите программу, которая складывает два дробных числа.
- Входные данные: a = 2.5, b = 3.5.
- Решение:java
double sum = a + b; System.out.println("Сумма: " + sum);
Вычисление среднего арифметического: Напишите программу, которая находит среднее арифметическое трех чисел.
- Входные данные: a = 2, b = 3, c = 4.
- Решение:java
double average = (a + b + c) / 3.0; System.out.println("Среднее: " + average);
Сравнение дробных чисел: Напишите программу, которая сравнивает два дробных числа и выводит большее.
- Входные данные: a = 5.5, b = 4.2.
- Решение:java
double max = Math.max(a, b); System.out.println("Большее число: " + max);
Вычисление площади круга: Напишите программу, которая вычисляет площадь круга.
- Входные данные: radius = 5.
- Решение:java
double area = Math.PI * Math.pow(radius, 2); System.out.println("Площадь круга: " + area);
Конвертация единиц измерения: Напишите программу, которая конвертирует километры в мили.
- Входные данные: kilometers = 5.
- Решение:java
double miles = kilometers * 0.621371; System.out.println("Мили: " + miles);
Вычисление дисперсии: Напишите программу, которая вычисляет дисперсию двух чисел.
- Входные данные: a = 4, b = 6.
- Решение:java
double variance = Math.pow((a - b), 2); System.out.println("Дисперсия: " + variance);
Вычисление факториала: Напишите программу, которая вычисляет факториал числа.
- Входные данные: n = 5.
- Решение:java
int factorial = 1; for (int i = 1; i <= n; i++) { factorial *= i; } System.out.println("Факториал: " + factorial);
Вычисление площади треугольника: Напишите программу, которая вычисляет площадь треугольника по формуле Герона.
- Входные данные: a = 5, b = 6, c = 7.
- Решение:java
double s = (a + b + c) / 2.0; double area = Math.sqrt(s * (s - a) * (s - b) * (s - c)); System.out.println("Площадь треугольника: " + area);
Проверка числа на простоту: Напишите программу, которая проверяет, является ли число простым.
- Входные данные: n = 7.
- Решение:java
boolean isPrime = true; for (int i = 2; i <= Math.sqrt(n); i++) { if (n % i == 0) { isPrime = false; break; } } System.out.println(n + " является простым: " + isPrime);
Поиск корней квадратного уравнения: Напишите программу, которая находит корни квадратного уравнения.
- Входные данные: a = 1, b = -3, c = 2.
- Решение:java
double discriminant = Math.pow(b, 2) - 4 * a * c; if (discriminant > 0) { double root1 = (-b + Math.sqrt(discriminant)) / (2 * a); double root2 = (-b - Math.sqrt(discriminant)) / (2 * a); System.out.println("Корни: " + root1 + ", " + root2); } else if (discriminant == 0) { double root = -b / (2 * a); System.out.println("Корень: " + root); } else { System.out.println("Корней нет"); }
5. УПРАВЛЯЮЩИЕ КОНСТРУКЦИИ
Базовые задачи:
Проверка четности числа: Напишите программу, которая проверяет, является ли число четным.
- Входные данные: a = 4.
- Решение:java
if (a % 2 == 0) { System.out.println(a + " четное число"); } else { System.out.println(a + " нечетное число"); }
Поиск большего из двух чисел: Напишите программу, которая находит большее из двух чисел.
- Входные данные: a = 5, b = 10.
- Решение:java
if (a > b) { System.out.println(a + " больше " + b); } else { System.out.println(b + " больше " + a); }
Проверка возраста: Напишите программу, которая проверяет, достиг ли пользователь 18 лет.
- Входные данные: age = 17.
- Решение:java
if (age >= 18) { System.out.println("Вы достигли 18 лет"); } else { System.out.println("Вы еще не достигли 18 лет"); }
Вывод дней недели: Напишите программу, которая выводит день недели по номеру.
- Входные данные: day = 3.
- Решение:java
switch (day) { case 1: System.out.println("Понедельник"); break; case 2: System.out.println("Вторник"); break; case 3: System.out.println("Среда"); break; case 4: System.out.println("Четверг"); break; case 5: System.out.println("Пятница"); break; case 6: System.out.println("Суббота"); break; case 7: System.out.println("Воскресенье"); break; default: System.out.println("Некорректный ввод"); }
Проверка числа на положительность: Напишите программу, которая проверяет, является ли число положительным.
- Входные данные: a = -5.
- Решение:java
if (a > 0) { System.out.println(a + " положительное число"); } else { System.out.println(a + " не положительное число"); }
Нахождение максимума из трех чисел: Напишите программу, которая находит максимум среди трех чисел.
- Входные данные: a = 5, b = 10, c = 3.
- Решение:java
int max = Math.max(a, Math.max(b, c)); System.out.println("Максимум: " + max);
Проверка на палиндром: Напишите программу, которая проверяет, является ли строка палиндромом.
- Входные данные: str = "madam".
- Решение:java
String reversed = new StringBuilder(str).reverse().toString(); if (str.equals(reversed)) { System.out.println(str + " палиндром"); } else { System.out.println(str + " не палиндром"); }
Классификация числа: Напишите программу, которая классифицирует число как положительное, отрицательное или ноль.
- Входные данные: a = 0.
- Решение:java
if (a > 0) { System.out.println(a + " положительное число"); } else if (a < 0) { System.out.println(a + " отрицательное число"); } else { System.out.println("Это ноль"); }
Вывод таблицы умножения: Напишите программу, которая выводит таблицу умножения для числа n.
- Входные данные: n = 3.
- Решение:java
for (int i = 1; i <= 10; i++) { System.out.println(n + " * " + i + " = " + (n * i)); }
Проверка на високосный год: Напишите программу, которая проверяет, является ли год високосным.
- Входные данные: year = 2024.
- Решение:java
if ((year % 4 == 0 && year % 100 != 0) || (year % 400 == 0)) { System.out.println(year + " високосный год"); } else { System.out.println(year + " не високосный год"); }
Сложные задачи:
Сумма четных и нечетных чисел: Напишите программу, которая находит сумму четных и нечетных чисел от 1 до n.
- Входные данные: n = 10.
- Решение:java
int evenSum = 0, oddSum = 0; for (int i = 1; i <= n; i++) { if (i % 2 == 0) { evenSum += i; } else { oddSum += i; } } System.out.println("Сумма четных: " + evenSum); System.out.println("Сумма нечетных: " + oddSum);
Генерация случайных чисел: Напишите программу, которая генерирует 5 случайных чисел и находит их сумму.
- Решение:java
Random random = new Random(); int sum = 0; for (int i = 0; i < 5; i++) { int num = random.nextInt(100); // случайное число от 0 до 99 sum += num; System.out.println("Случайное число: " + num); } System.out.println("Сумма случайных чисел: " + sum);
- Решение:
Проверка, является ли число квадратом другого числа: Напишите программу, которая проверяет, является ли одно число квадратом другого.
- Входные данные: a = 4, b = 2.
- Решение:java
if (b * b == a) { System.out.println(a + " является квадратом " + b); } else { System.out.println(a + " не является квадратом " + b); }
Сумма цифр числа: Напишите программу, которая вычисляет сумму цифр числа.
- Входные данные: n = 1234.
- Решение:java
int sum = 0; while (n != 0) { sum += n % 10; n /= 10; } System.out.println("Сумма цифр: " + sum);
Поиск минимального и максимального числа в массиве: Напишите программу, которая находит минимальное и максимальное число в массиве.
- Входные данные: int[] numbers = {3, 1, 4, 1, 5}.
- Решение:java
int min = numbers[0], max = numbers[0]; for (int number : numbers) { if (number < min) { min = number; } if (number > max) { max = number; } } System.out.println("Минимальное: " + min); System.out.println("Максимальное: " + max);
Сортировка массива: Напишите программу, которая сортирует массив чисел по возрастанию.
- Входные данные: int[] numbers = {5, 3, 8, 1, 4}.
- Решение:java
Arrays.sort(numbers); System.out.println("Отсортированный массив: " + Arrays.toString(numbers));
Поиск второго по величине числа в массиве: Напишите программу, которая находит второе по величине число в массиве.
- Входные данные: int[] numbers = {5, 1, 3, 4, 2}.
- Решение:java
Arrays.sort(numbers); System.out.println("Второе по величине: " + numbers[numbers.length - 2]);
Проверка, является ли строка анаграммой: Напишите программу, которая проверяет, являются ли две строки анаграммами.
- Входные данные: str1 = "listen", str2 = "silent".
- Решение:java
char[] arr1 = str1.toCharArray(); char[] arr2 = str2.toCharArray(); Arrays.sort(arr1); Arrays.sort(arr2); boolean isAnagram = Arrays.equals(arr1, arr2); System.out.println("Являются ли анаграммами: " + isAnagram);
Вычисление произведения чисел от 1 до n: Напишите программу, которая вычисляет произведение всех чисел от 1 до n.
- Входные данные: n = 5.
- Решение:java
long product = 1; for (int i = 1; i <= n; i++) { product *= i; } System.out.println("Произведение: " + product);
Поиск повторяющихся элементов в массиве: Напишите программу, которая находит повторяющиеся элементы в массиве.
- Входные данные: int[] numbers = {1, 2, 3, 1, 2}.
- Решение:java
Set<Integer> seen = new HashSet<>(); Set<Integer> duplicates = new HashSet<>(); for (int number : numbers) { if (!seen.add(number)) { duplicates.add(number); } } System.out.println("Повторяющиеся элементы: " + duplicates);
6. ЦИКЛЫ
Базовые задачи:
Цикл for: Напишите программу, которая выводит числа от 1 до 10 с использованием цикла for.
- Решение:java
for (int i = 1; i <= 10; i++) { System.out.println(i); }
- Решение:
Цикл while: Напишите программу, которая выводит числа от 1 до 10 с использованием цикла while.
- Решение:java
int i = 1; while (i <= 10) { System.out.println(i); i++; }
- Решение:
Цикл do-while: Напишите программу, которая выводит числа от 1 до 10 с использованием цикла do-while.
- Решение:java
int i = 1; do { System.out.println(i); i++; } while (i <= 10);
- Решение:
Сумма чисел от 1 до n: Напишите программу, которая вычисляет сумму чисел от 1 до n.
- Входные данные: n = 5.
- Решение:java
int sum = 0; for (int i = 1; i <= n; i++) { sum += i; } System.out.println("Сумма: " + sum);
Вывод четных чисел: Напишите программу, которая выводит все четные числа от 1 до n.
- Входные данные: n = 10.
- Решение:java
for (int i = 1; i <= n; i++) { if (i % 2 == 0) { System.out.println(i); } }
Вывод нечетных чисел: Напишите программу, которая выводит все нечетные числа от 1 до n.
- Входные данные: n = 10.
- Решение:java
for (int i = 1; i <= n; i++) { if (i % 2 != 0) { System.out.println(i); } }
Обратный отсчет: Напишите программу, которая выполняет обратный отсчет от n до 1.
- Входные данные: n = 5.
- Решение:java
for (int i = n; i >= 1; i--) { System.out.println(i); }
Поиск факториала с помощью цикла: Напишите программу, которая вычисляет факториал числа n с использованием цикла.
- Входные данные: n = 5.
- Решение:java
int factorial = 1; for (int i = 1; i <= n; i++) { factorial *= i; } System.out.println("Факториал: " + factorial);
Поиск чисел Фибоначчи: Напишите программу, которая выводит первые n чисел Фибоначчи.
- Входные данные: n = 5.
- Решение:java
int a = 0, b = 1; for (int i = 1; i <= n; i++) { System.out.println(a); int next = a + b; a = b; b = next; }
Сумма цифр числа с помощью цикла: Напишите программу, которая вычисляет сумму цифр числа с использованием цикла.
- Входные данные: n = 123.
- Решение:java
int sum = 0; while (n != 0) { sum += n % 10; n /= 10; } System.out.println("Сумма цифр: " + sum);
Сложные задачи:
Обратная строка: Напишите программу, которая переворачивает строку.
- Входные данные: str = "hello".
- Решение:java
String reversed = ""; for (int i = str.length() - 1; i >= 0; i--) { reversed += str.charAt(i); } System.out.println("Перевернутая строка: " + reversed);
Проверка числа на простоту: Напишите программу, которая проверяет, является ли число простым.
- Входные данные: n = 7.
- Решение:java
boolean isPrime = true; if (n <= 1) { isPrime = false; } else { for (int i = 2; i <= Math.sqrt(n); i++) { if (n % i == 0) { isPrime = false; break; } } } System.out.println(n + " является простым: " + isPrime);
Печать треугольника звезд: Напишите программу, которая выводит треугольник из звезд.
- Входные данные: n = 5.
- Решение:java
for (int i = 1; i <= n; i++) { for (int j = 1; j <= i; j++) { System.out.print("* "); } System.out.println(); }
Поиск второго по величине числа: Напишите программу, которая находит второе по величине число в массиве.
- Входные данные: int[] numbers = {5, 3, 8, 1, 4}.
- Решение:java
int max = Integer.MIN_VALUE; int secondMax = Integer.MIN_VALUE; for (int number : numbers) { if (number > max) { secondMax = max; max = number; } else if (number > secondMax && number != max) { secondMax = number; } } System.out.println("Второе по величине: " + secondMax);
Сумма квадратов: Напишите программу, которая вычисляет сумму квадратов чисел от 1 до n.
- Входные данные: n = 5.
- Решение:java
int sumOfSquares = 0; for (int i = 1; i <= n; i++) { sumOfSquares += i * i; } System.out.println("Сумма квадратов: " + sumOfSquares);
7. МАССИВЫ И КОЛЛЕКЦИИ
Базовые задачи:
Инициализация массива: Создайте и инициализируйте массив целых чисел.
- Решение:java
int[] numbers = {1, 2, 3, 4, 5};
- Решение:
Вывод элементов массива: Напишите программу, которая выводит элементы массива.
- Входные данные: int[] numbers = {1, 2, 3, 4, 5}.
- Решение:java
for (int number : numbers) { System.out.println(number); }
Сумма элементов массива: Напишите программу, которая вычисляет сумму элементов массива.
- Входные данные: int[] numbers = {1, 2, 3, 4, 5}.
- Решение:java
int sum = 0; for (int number : numbers) { sum += number; } System.out.println("Сумма: " + sum);
Поиск максимального элемента в массиве: Напишите программу, которая находит максимальный элемент в массиве.
- Входные данные: int[] numbers = {1, 2, 3, 4, 5}.
- Решение:java
int max = numbers[0]; for (int number : numbers) { if (number > max) { max = number; } } System.out.println("Максимальный элемент: " + max);
Поиск минимального элемента в массиве: Напишите программу, которая находит минимальный элемент в массиве.
- Входные данные: int[] numbers = {1, 2, 3, 4, 5}.
- Решение:java
int min = numbers[0]; for (int number : numbers) { if (number < min) { min = number; } } System.out.println("Минимальный элемент: " + min);
Копирование массива: Напишите программу, которая копирует массив.
- Входные данные: int[] original = {1, 2, 3, 4, 5}.
- Решение:java
int[] copy = Arrays.copyOf(original, original.length);
Сортировка массива: Напишите программу, которая сортирует массив.
- Входные данные: int[] numbers = {5, 3, 8, 1, 4}.
- Решение:java
Arrays.sort(numbers);
Объединение массивов: Напишите программу, которая объединяет два массива.
- Входные данные: int[] array1 = {1, 2, 3}, array2 = {4, 5, 6}.
- Решение:java
int[] combined = new int[array1.length + array2.length]; System.arraycopy(array1, 0, combined, 0, array1.length); System.arraycopy(array2, 0, combined, array1.length, array2.length);
Удаление элемента из массива: Напишите программу, которая удаляет элемент из массива.
- Входные данные: int[] numbers = {1, 2, 3, 4, 5}, indexToRemove = 2.
- Решение:java
int[] newNumbers = new int[numbers.length - 1]; for (int i = 0, j = 0; i < numbers.length; i++) { if (i != indexToRemove) { newNumbers[j++] = numbers[i]; } }
Сравнение массивов: Напишите программу, которая сравнивает два массива на равенство.
- Входные данные: int[] array1 = {1, 2, 3}, array2 = {1, 2, 3}.
- Решение:java
boolean areEqual = Arrays.equals(array1, array2); System.out.println("Массивы равны: " + areEqual);
Сложные задачи:
Поиск второго по величине элемента в массиве: Напишите программу, которая находит второй по величине элемент в массиве.
- Входные данные: int[] numbers = {5, 1, 3, 4, 2}.
- Решение:java
int max = Integer.MIN_VALUE; int secondMax = Integer.MIN_VALUE; for (int number : numbers) { if (number > max) { secondMax = max; max = number; } else if (number > secondMax && number != max) { secondMax = number; } } System.out.println("Второй по величине: " + secondMax);
Перевернуть массив: Напишите программу, которая переворачивает массив.
- Входные данные: int[] numbers = {1, 2, 3, 4, 5}.
- Решение:java
int[] reversed = new int[numbers.length]; for (int i = 0; i < numbers.length; i++) { reversed[i] = numbers[numbers.length - 1 - i]; }
Уникальные элементы: Напишите программу, которая находит уникальные элементы в массиве.
- Входные данные: int[] numbers = {1, 2, 2, 3, 4, 4}.
- Решение:java
Set<Integer> uniqueNumbers = new HashSet<>(); for (int number : numbers) { uniqueNumbers.add(number); } System.out.println("Уникальные элементы: " + uniqueNumbers);
Поиск максимальной последовательности: Напишите программу, которая находит максимальную последовательность одинаковых элементов в массиве.
- Входные данные: int[] numbers = {1, 1, 2, 2, 2, 3, 3}.
- Решение:java
int maxCount = 1, currentCount = 1; for (int i = 1; i < numbers.length; i++) { if (numbers[i] == numbers[i - 1]) { currentCount++; } else { if (currentCount > maxCount) { maxCount = currentCount; } currentCount = 1; } } maxCount = Math.max(maxCount, currentCount); System.out.println("Максимальная последовательность: " + maxCount);
Сортировка массива по возрастанию: Напишите программу, которая сортирует массив по возрастанию.
- Входные данные: int[] numbers = {5, 3, 8, 1, 4}.
- Решение:java
Arrays.sort(numbers);
8. КЛАССЫ И ОБЪЕКТЫ
Базовые задачи:
Создание класса: Создайте класс
Personс полямиnameиage.- Решение:java
class Person { String name; int age; }
- Решение:
Конструктор: Добавьте конструктор в класс
Person, который инициализирует поля.- Решение:java
class Person { String name; int age; Person(String name, int age) { this.name = name; this.age = age; } }
- Решение:
Метод для вывода информации: Добавьте метод
displayInfo, который выводит информацию о человеке.- Решение:java
class Person { String name; int age; Person(String name, int age) { this.name = name; this.age = age; } void displayInfo() { System.out.println("Name: " + name + ", Age: " + age); } }
- Решение:
Создание объектов: Создайте объекты класса
Personи вызовите методdisplayInfo.- Решение:java
public class Main { public static void main(String[] args) { Person person1 = new Person("Alice", 30); Person person2 = new Person("Bob", 25); person1.displayInfo(); person2.displayInfo(); } }
- Решение:
Методы геттеры и сеттеры: Добавьте геттеры и сеттеры для полей класса
Person.- Решение:java
class Person { private String name; private int age; Person(String name, int age) { this.name = name; this.age = age; } String getName() { return name; } void setName(String name) { this.name = name; } int getAge() { return age; } void setAge(int age) { this.age = age; } }
- Решение:
Переопределение метода toString: Переопределите метод
toStringдля классаPerson.- Решение:java
class Person { private String name; private int age; Person(String name, int age) { this.name = name; this.age = age; } @Override public String toString() { return "Person{name='" + name + "', age=" + age + '}'; } }
- Решение:
Наследование: Создайте класс
Student, который наследует классPersonи добавляет полеstudentId.- Решение:java
class Student extends Person { private String studentId; Student(String name, int age, String studentId) { super(name, age); this.studentId = studentId; } }
- Решение:
Методы в классе-наследнике: Добавьте метод
displayStudentInfoв классStudent, который выводит информацию о студенте.- Решение:java
class Student extends Person { private String studentId; Student(String name, int age, String studentId) { super(name, age); this.studentId = studentId; } void displayStudentInfo() { displayInfo(); System.out.println("Student ID: " + studentId); } }
- Решение:
Полиморфизм: Создайте метод, который принимает объект типа
Personи вызываетdisplayInfo.- Решение:java
void showInfo(Person person) { person.displayInfo(); }
- Решение:
Интерфейсы: Создайте интерфейс
Animalс методомsound, и реализуйте его в классеDog.- Решение:java
interface Animal { void sound(); } class Dog implements Animal { public void sound() { System.out.println("Гав!"); } }
- Решение:
Сложные задачи:
Создание класса с массивом: Создайте класс
School, который содержит массив объектовStudent.- Решение:java
class School { private Student[] students; School(Student[] students) { this.students = students; } }
- Решение:
Метод для подсчета студентов: Добавьте метод
countStudentsв классSchool, который возвращает количество студентов.- Решение:java
class School { private Student[] students; School(Student[] students) { this.students = students; } int countStudents() { return students.length; } }
- Решение:
Поиск студента по ID: Добавьте метод
findStudentByIdв классSchool, который ищет студента по ID.- Решение:java
class School { private Student[] students; School(Student[] students) { this.students = students; } Student findStudentById(String studentId) { for (Student student : students) { if (student.getStudentId().equals(studentId)) { return student; } } return null; } }
- Решение:
Класс с внутренним классом: Создайте класс
Library, который содержит внутренний классBook.- Решение:java
class Library { class Book { private String title; Book(String title) { this.title = title; } } }
- Решение:
Статические методы: Добавьте статический метод
createStudentв классStudent, который создает нового студента.- Решение:java
class Student extends Person { private String studentId; Student(String name, int age, String studentId) { super(name, age); this.studentId = studentId; } static Student createStudent(String name, int age, String studentId) { return new Student(name, age, studentId); } }
- Решение:
9. ИСКЛЮЧЕНИЯ И ОБРАБОТКА ОШИБОК
Базовые задачи:
Обработка исключения деления на ноль: Напишите программу, которая обрабатывает исключение деления на ноль.
- Решение:java
try { int result = 10 / 0; } catch (ArithmeticException e) { System.out.println("Ошибка: деление на ноль."); }
- Решение:
Обработка исключения массива: Напишите программу, которая обрабатывает исключение выхода за пределы массива.
- Решение:java
int[] numbers = {1, 2, 3}; try { System.out.println(numbers[5]); } catch (ArrayIndexOutOfBoundsException e) { System.out.println("Ошибка: выход за пределы массива."); }
- Решение:
Создание собственного исключения: Создайте собственное исключение
InvalidAgeException.- Решение:java
class InvalidAgeException extends Exception { public InvalidAgeException(String message) { super(message); } }
- Решение:
Использование собственного исключения: Используйте
InvalidAgeExceptionв методе, который проверяет возраст.- Решение:java
void checkAge(int age) throws InvalidAgeException { if (age < 0) { throw new InvalidAgeException("Возраст не может быть отрицательным."); } }
- Решение:
Множественная обработка исключений: Обработайте несколько типов исключений в одном блоке
catch.- Решение:java
try { int result = 10 / 0; int[] numbers = {1, 2, 3}; System.out.println(numbers[5]); } catch (ArithmeticException | ArrayIndexOutOfBoundsException e) { System.out.println("Ошибка: " + e.getMessage()); }
- Решение:
finally блок: Используйте блок
finallyдля выполнения кода независимо от исключений.- Решение:java
try { int result = 10 / 0; } catch (ArithmeticException e) { System.out.println("Ошибка: деление на ноль."); } finally { System.out.println("Этот блок выполнится всегда."); }
- Решение:
Проверка на наличие исключения: Напишите метод, который выбрасывает исключение, если число меньше 0.
- Решение:java
void validateNumber(int number) throws Exception { if (number < 0) { throw new Exception("Число не должно быть меньше 0."); } }
- Решение:
Логирование ошибок: Логируйте ошибки в файл при возникновении исключений.
- Решение:java
import java.io.FileWriter; import java.io.IOException; try { int result = 10 / 0; } catch (ArithmeticException e) { try (FileWriter writer = new FileWriter("error.log", true)) { writer.write("Ошибка: " + e.getMessage() + "\n"); } catch (IOException ioException) { ioException.printStackTrace(); } }
- Решение:
Создание и использование нескольких исключений: Создайте несколько собственных исключений и используйте их в коде.
- Решение:java
class InvalidNameException extends Exception { public InvalidNameException(String message) { super(message); } } class InvalidAgeException extends Exception { public InvalidAgeException(String message) { super(message); } } void validate(String name, int age) throws InvalidNameException, InvalidAgeException { if (name == null || name.isEmpty()) { throw new InvalidNameException("Имя не может быть пустым."); } if (age < 0) { throw new InvalidAgeException("Возраст не может быть отрицательным."); } }
- Решение:
Пользовательское сообщение об ошибке: Выводите пользовательские сообщения об ошибках в блоке catch.
- Решение:java
try { int result = 10 / 0; } catch (ArithmeticException e) { System.out.println("Пользовательская ошибка: Не удается разделить на ноль."); }
- Решение:
Сложные задачи:
Создание и обработка исключений в классе: Создайте класс, который выбрасывает исключение, если вводимое значение невалидно.
- Решение:java
class Validator { void validateInput(String input) throws InvalidInputException { if (input == null || input.isEmpty()) { throw new InvalidInputException("Недопустимый ввод."); } } }
- Решение:
Иерархия исключений: Создайте иерархию исключений для различных ошибок.
- Решение:java
class AppException extends Exception {} class DatabaseException extends AppException {} class NetworkException extends AppException {}
- Решение:
Обработка исключений в нескольких методах: Напишите программу, где исключения обрабатываются на разных уровнях.
- Решение:java
void methodA() throws Exception { methodB(); } void methodB() throws Exception { throw new Exception("Ошибка в методе B"); } void run() { try { methodA(); } catch (Exception e) { System.out.println("Обработано в run: " + e.getMessage()); } }
- Решение:
Вывод стека вызовов: Используйте
printStackTraceдля вывода информации о возникшем исключении.- Решение:java
try { int result = 10 / 0; } catch (ArithmeticException e) { e.printStackTrace(); }
- Решение:
Создание исключения с деталями: Добавьте детали в ваше пользовательское исключение, такие как код ошибки.
- Решение:java
class CustomException extends Exception { private int errorCode; CustomException(String message, int errorCode) { super(message); this.errorCode = errorCode; } int getErrorCode() { return errorCode; } }
- Решение:
10. ОСНОВЫ РАБОТЫ С ФАЙЛАМИ
Базовые задачи:
Чтение из файла: Напишите программу, которая читает текст из файла.
- Решение:java
import java.io.BufferedReader; import java.io.FileReader; import java.io.IOException; public class FileReadExample { public static void main(String[] args) { try (BufferedReader br = new BufferedReader(new FileReader("example.txt"))) { String line; while ((line = br.readLine()) != null) { System.out.println(line); } } catch (IOException e) { e.printStackTrace(); } } }
- Решение:
Запись в файл: Напишите программу, которая записывает текст в файл.
- Решение:java
import java.io.BufferedWriter; import java.io.FileWriter; import java.io.IOException; public class FileWriteExample { public static void main(String[] args) { try (BufferedWriter bw = new BufferedWriter(new FileWriter("example.txt"))) { bw.write("Hello, World!"); } catch (IOException e) { e.printStackTrace(); } } }
- Решение:
Добавление текста в файл: Напишите программу, которая добавляет текст в существующий файл.
- Решение:java
import java.io.BufferedWriter; import java.io.FileWriter; import java.io.IOException; public class FileAppendExample { public static void main(String[] args) { try (BufferedWriter bw = new BufferedWriter(new FileWriter("example.txt", true))) { bw.write("\nAppending some text."); } catch (IOException e) { e.printStackTrace(); } } }
- Решение:
Проверка существования файла: Напишите программу, которая проверяет, существует ли файл.
- Решение:java
import java.io.File; public class FileExistsExample { public static void main(String[] args) { File file = new File("example.txt"); if (file.exists()) { System.out.println("Файл существует."); } else { System.out.println("Файл не существует."); } } }
- Решение:
Удаление файла: Напишите программу, которая удаляет файл.
- Решение:java
import java.io.File; public class FileDeleteExample { public static void main(String[] args) { File file = new File("example.txt"); if (file.delete()) { System.out.println("Файл удален."); } else { System.out.println("Не удалось удалить файл."); } } }
- Решение:
Список файлов в директории: Напишите программу, которая выводит список файлов в заданной директории.
- Решение:java
import java.io.File; public class ListFilesExample { public static void main(String[] args) { File folder = new File("path/to/directory"); File[] files = folder.listFiles(); if (files != null) { for (File file : files) { System.out.println(file.getName()); } } } }
- Решение:
Чтение бинарного файла: Напишите программу, которая читает данные из бинарного файла.
- Решение:java
import java.io.FileInputStream; import java.io.IOException; public class BinaryFileReadExample { public static void main(String[] args) { try (FileInputStream fis = new FileInputStream("example.bin")) { int data; while ((data = fis.read()) != -1) { System.out.print((char) data); } } catch (IOException e) { e.printStackTrace(); } } }
- Решение:
Запись в бинарный файл: Напишите программу, которая записывает данные в бинарный файл.
- Решение:java
import java.io.FileOutputStream; import java.io.IOException; public class BinaryFileWriteExample { public static void main(String[] args) { try (FileOutputStream fos = new FileOutputStream("example.bin")) { fos.write('H'); fos.write('i'); } catch (IOException e) { e.printStackTrace(); } } }
- Решение:
Копирование файла: Напишите программу, которая копирует один файл в другой.
- Решение:java
import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.IOException; public class FileCopyExample { public static void main(String[] args) { try (FileInputStream fis = new FileInputStream("source.txt"); FileOutputStream fos = new FileOutputStream("destination.txt")) { byte[] buffer = new byte[1024]; int length; while ((length = fis.read(buffer)) > 0) { fos.write(buffer, 0, length); } } catch (IOException e) { e.printStackTrace(); } } }
- Решение:
Чтение файла построчно с использованием
Files: ИспользуйтеFilesдля чтения файла построчно.- Решение:java
import java.nio.file.Files; import java.nio.file.Paths; import java.io.IOException; public class FileReadNIOExample { public static void main(String[] args) { try { Files.lines(Paths.get("example.txt")).forEach(System.out::println); } catch (IOException e) { e.printStackTrace(); } } }
- Решение:
Сложные задачи:
Создание текстового файла с данными: Напишите программу, которая создает текстовый файл и записывает в него данные.
- Решение:java
import java.io.BufferedWriter; import java.io.FileWriter; import java.io.IOException; public class CreateTextFileExample { public static void main(String[] args) { try (BufferedWriter bw = new BufferedWriter(new FileWriter("data.txt"))) { bw.write("Sample data"); } catch (IOException e) { e.printStackTrace(); } } }
- Решение:
Запись объектов в файл с использованием сериализации: Напишите программу, которая сериализует объект и записывает его в файл.
- Решение:java
import java.io.FileOutputStream; import java.io.IOException; import java.io.ObjectOutputStream; import java.io.Serializable; class Student implements Serializable { String name; int age; Student(String name, int age) { this.name = name; this.age = age; } } public class SerializeExample { public static void main(String[] args) { Student student = new Student("Alice", 20); try (FileOutputStream fos = new FileOutputStream("student.ser"); ObjectOutputStream oos = new ObjectOutputStream(fos)) { oos.writeObject(student); } catch (IOException e) { e.printStackTrace(); } } }
- Решение:
Чтение объектов из файла с использованием десериализации: Напишите программу, которая десериализует объект из файла.
- Решение:java
import java.io.FileInputStream; import java.io.IOException; import java.io.ObjectInputStream; import java.io.Serializable; class Student implements Serializable { String name; int age; Student(String name, int age) { this.name = name; this.age = age; } } public class DeserializeExample { public static void main(String[] args) { try (FileInputStream fis = new FileInputStream("student.ser"); ObjectInputStream ois = new ObjectInputStream(fis)) { Student student = (Student) ois.readObject(); System.out.println("Name: " + student.name + ", Age: " + student.age); } catch (IOException | ClassNotFoundException e) { e.printStackTrace(); } } }
- Решение:
Обработка файла с помощью
FilesиStream: ИспользуйтеFilesи потоки для обработки содержимого файла.- Решение:java
import java.nio.file.Files; import java.nio.file.Paths; import java.io.IOException; import java.util.List; public class FileProcessingExample { public static void main(String[] args) { try { List<String> lines = Files.readAllLines(Paths.get("data.txt")); lines.forEach(System.out::println); } catch (IOException e) { e.printStackTrace(); } } }
- Решение:
Создание и использование файловой структуры: Создайте программу для управления файлами (создание, удаление, копирование).
- Решение:java
import java.io.File; import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.IOException; public class FileManager { public void createFile(String fileName) throws IOException { new File(fileName).createNewFile(); } public void deleteFile(String fileName) { new File(fileName).delete(); } public void copyFile(String source, String destination) throws IOException { try (FileInputStream fis = new FileInputStream(source); FileOutputStream fos = new FileOutputStream(destination)) { byte[] buffer = new byte[1024]; int length; while ((length = fis.read(buffer)) > 0) { fos.write(buffer, 0, length); } } } }
- Решение:
Java является объектно-ориентированным языком, поэтому такие понятия как "класс" и "объект" играют в нем ключевую роль. Любую программу на Java можно представить как набор взаимодействующих между собой объектов.
Шаблоном или описанием объекта является класс, а объект представляет экземпляр этого класса. Можно еще провести следующую аналогию. У нас у всех есть некоторое представление о человеке - наличие двух рук, двух ног, головы, туловища и т.д. Есть некоторый шаблон - этот шаблон можно назвать классом. Реально же существующий человек (фактически экземпляр данного класса) является объектом этого класса.
Класс определяется с помощью ключевого слова сlass:
1 2 3 | class Person{} |
В данном случае класс называется Person. После названия класса идут фигурные скобки, между которыми помещается тело класса - то есть его поля и методы.
Любой объект может обладать двумя основными характеристиками: состояние - некоторые данные, которые хранит объект, и поведение - действия, которые может совершать объект.
Для хранения состояния объекта в классе применяются поля или переменные класса. Для определения поведения объекта в классе применяются методы. Например, класс Person, который представляет человека, мог бы иметь следующее определение:
1 2 3 4 5 6 7 8 | class Person{ String name; // имя int age; // возраст void displayInfo(){ System.out.printf("Name: %s \tAge: %d\n", name, age); }} |
В классе Person определены два поля: name представляет имя человека, а age - его возраст. И также определен метод displayInfo, который ничего не возвращает и просто выводит эти данные на консоль.
Теперь используем данный класс. Для этого определим следующую программу:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | public class Program{ public static void main(String[] args) { Person tom; }}class Person{ String name; // имя int age; // возраст void displayInfo(){ System.out.printf("Name: %s \tAge: %d\n", name, age); }} |
Как правило, классы определяются в разных файлах. В данном случае для простоты мы определяем два класса в одном файле. Стоит отметить, что в этом случае только один класс может иметь модификатор public (в данном случае это класс Program), а сам файл кода должен называться по имени этого класса, то есть в данном случае файл должен называться Program.java.
Класс представляет новый тип, поэтому мы можем определять переменные, которые представляют данный тип. Так, здесь в методе main определена переменная
tom, которая представляет класс Person. Но пока эта переменная не указывает ни на какой объект и по умолчанию она имеет значение null.
По большому счету мы ее пока не можем использовать, поэтому вначале необходимо создать объект класса Person.
Конструкторы
Кроме обычных методов классы могут определять специальные методы, которые называются конструкторами. Конструкторы вызываются при создании нового объекта данного класса. Конструкторы выполняют инициализацию объекта.
Если в классе не определено ни одного конструктора, то для этого класса автоматически создается конструктор без параметров.
Выше определенный класс Person не имеет никаких конструкторов. Поэтому для него автоматически создается конструктор по умолчанию, который мы можем использовать для создания объекта Person. В частности, создадим один объект:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 | public class Program{ public static void main(String[] args) { Person tom = new Person(); // создание объекта tom.displayInfo(); // изменяем имя и возраст tom.name = "Tom"; tom.age = 34; tom.displayInfo(); }}class Person{ String name; // имя int age; // возраст void displayInfo(){ System.out.printf("Name: %s \tAge: %d\n", name, age); }} |
Для создания объекта Person используется выражение new Person(). Оператор new выделяет память для объекта
Person. И затем вызывается конструктор по умолчанию, который не принимает никаких параметров. В итоге после выполнения данного выражения в памяти
будет выделен участок, где будут храниться все данные объекта Person. А переменная tom получит ссылку на созданный объект.
Если конструктор не инициализирует значения переменных объекта, то они получают значения по умолчанию. Для переменных числовых типов это число 0, а для типа string и классов - это значение null (то есть фактически отсутствие значения).
После создания объекта мы можем обратиться к переменным объекта Person через переменную tom и установить или получить их значения, например, tom.name = "Tom".
В итоге мы увидим на консоли:
Name: null Age: 0 Name: Tom Age: 34
Если необходимо, чтобы при создании объекта производилась какая-то логика, например, чтобы поля класса получали какие-то определенные значения, то можно определить в классе свои конструкторы. Например:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 | public class Program{ public static void main(String[] args) { Person bob = new Person(); // вызов первого конструктора без параметров bob.displayInfo(); Person tom = new Person("Tom"); // вызов второго конструктора с одним параметром tom.displayInfo(); Person sam = new Person("Sam", 25); // вызов третьего конструктора с двумя параметрами sam.displayInfo(); }}class Person{ String name; // имя int age; // возраст Person() { name = "Undefined"; age = 18; } Person(String n) { name = n; age = 18; } Person(String n, int a) { name = n; age = a; } void displayInfo(){ System.out.printf("Name: %s \tAge: %d\n", name, age); }} |
Теперь в классе определено три коструктора, каждый из которых принимает различное количество параметров и устанавливает значения полей класса.
Консольный вывод программы:
Name: Undefined Age: 18 Name: Tom Age: 18 Name: Sam Age: 25
Ключевое слово this
Ключевое слово this представляет ссылку на текущий экземпляр класса. Через это ключевое слово мы можем обращаться к переменным, методам объекта, а также вызывать его конструкторы. Например:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 | public class Program{ public static void main(String[] args) { Person undef = new Person(); undef.displayInfo(); Person tom = new Person("Tom"); tom.displayInfo(); Person sam = new Person("Sam", 25); sam.displayInfo(); }}class Person{ String name; // имя int age; // возраст Person() { this("Undefined", 18); } Person(String name) { this(name, 18); } Person(String name, int age) { this.name = name; this.age = age; } void displayInfo(){ System.out.printf("Name: %s \tAge: %d\n", name, age); }} |
В третьем конструкторе параметры называются так же, как и поля класса. И чтобы разграничить поля и параметры, применяется ключевое слово this:
1 | this.name = name; |
Так, в данном случае указываем, что значение параметра name присваивается полю name.
Кроме того, у нас три конструктора, которые выполняют идентичные действия: устанавливают поля name и age. Чтобы избежать повторов, с помощью this можно вызвать один из конструкторов класса и передать для его параметров необходимые значения:
1 2 3 4 | Person(String name){ this(name, 18);} |
В итоге результат программы будет тот же, что и в предыдущем примере.
Инициализаторы
Кроме конструктора начальную инициализацию объекта вполне можно было проводить с помощью инициализатора объекта. Инициализатор выполняется до любого конструктора. То есть в инициализатор мы можем поместить код, общий для всех конструкторов:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 | public class Program{ public static void main(String[] args) { Person undef = new Person(); undef.displayInfo(); Person tom = new Person("Tom"); tom.displayInfo(); }}class Person{ String name; // имя int age; // возраст /*начало блока инициализатора*/ { name = "Undefined"; age = 18; } /*конец блока инициализатора*/ Person(){ } Person(String name){ this.name = name; } Person(String name, int age){ this.name = name; this.age = age; } void displayInfo(){ System.out.printf("Name: %s \tAge: %d\n", name, age); }} |
Консольный вывод:
Name: Undefined Age: 18 Name: Tom Age: 18
Как правило, в Java классы объединяются в пакеты. Пакеты позволяют организовать классы логически в наборы. По умолчанию java уже имеет ряд встроенных
пакетов, например, java.lang, java.util, java.io и т.д. Кроме того, пакеты могут иметь вложенные пакеты.
Организация классов в виде пакетов позволяет избежать конфликта имен между классами. Ведь нередки ситуации, когда разработчики называют свои классы одинаковыми именами. Принадлежность к пакету позволяет гарантировать однозначность имен.
Чтобы указать, что класс принадлежит определенному пакету, надо использовать директиву package, после которой указывается имя пакета:
1 | package название_пакета; |
Как правило, названия пакетов соответствуют физической структуре проекта, то есть организации каталогов, в которых находятся файлы с исходным кодом. А путь к файлам внутри проекта соответствует названию пакета этих файлов. Например, если классы принадлежат пакету mypack, то эти классы помещаются в проекте в папку mypack.
Классы необязательно определять в пакеты. Если для класса пакет не определен, то считается, что данный класс находится в пакете по умолчанию, который не имеет имени.
Например, создадим в папке для исходных файлов каталог study. В нем создадим файл Program.java со следующим кодом:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 | package study;public class Program{ public static void main(String[] args) { Person kate = new Person("Kate", 32); kate.displayInfo(); }}class Person{ String name; int age; Person(String name, int age){ this.name = name; this.age = age; } void displayInfo(){ System.out.printf("Name: %s \t Age: %d \n", name, age); }} |
Директива package study в начале файла указывает, что классы Program и Person, которые здесь определены, принадлежат пакету study.
Когда мы работаем в среде разработки, например, в Netbeans, то IDE берет на себя все вопросы компиляции пакетов и входящих в них файлов. Соответственно нам достаточно нажать на кнопку, и все будет готово. Однако если мы компилируем программу в командной строке, то мы можем столкнуться с некоторыми трудностями. Поэтому рассмотрим этот аспект.
Для компиляции программы вначале в командной строке/терминале с помощью команды cd перейдем к папке, где находится каталог study.
cd C:\java
Например, в моем случае это каталог C:\java (то есть файл с исходным кодом расположен по пути C:\java\study\Program.java).
Для компиляции выполним команду
javac study\Program.java
После этого в папке study появятся скомпилированные файлы Program.class и Person.class. Для запуска программы выполним команду:
java study.Program
Импорт пакетов и классов
Если нам надо использовать классы из других пакетов, то нам надо подключить эти пакеты и классы. Исключение составляют классы из пакета
java.lang (например, String), которые подключаются в программу автоматически.
Например, знакомый по прошлым темам класс Scanner находится в пакете java.util, поэтому мы можем получить к нему доступ следующим способом:
1 | java.util.Scanner in = new java.util.Scanner(System.in); |
То есть мы указываем полный путь к файлу в пакете при создании его объекта. Однако такое нагромождение имен пакетов не всегда удобно, и в качестве альтернативы мы можем импортировать пакеты и классы в проект с помощью директивы import, которая указывается после директивы package:
1 2 3 4 5 6 7 8 9 10 11 | package study;import java.util.Scanner; // импорт класса Scannerpublic class Program { public static void main(String[] args) { Scanner in = new Scanner(System.in); } } |
Директива import указывается в самом начале кода, после чего идет имя подключаемого класса (в данном случае класса Scanner).
В примере выше мы подключили только один класс, однако пакет java.util содержит еще множество классов. И чтобы не подключать по отдельности
каждый класс, мы можем сразу подключить весь пакет:
1 | import java.util.*; // импорт всех классов из пакета java.util |
Теперь мы можем использовать любой класс из пакета java.util.
Возможна ситуация, когда мы используем два класса с одним и тем же названием из двух разных пакетов, например, класс Date имеется и в пакете java.util, и в пакете java.sql. И если нам надо одновременно использовать два этих класса, то необходимо указывать полный путь к этим классам в пакете:
1 2 | java.util.Date utilDate = new java.util.Date();java.sql.Date sqlDate = new java.sql.Date(); |
Статический импорт
В java есть также особая форма импорта - статический импорт. Для этого вместе с директивой import используется модификатор
static:
1 2 3 4 5 6 7 8 9 10 11 12 13 | package study;import static java.lang.System.*;import static java.lang.Math.*;public class Program { public static void main(String[] args) { double result = sqrt(20); out.println(result); } } |
Здесь происходит статический импорт классов System и Math. Эти классы имеют статические методы. Благодаря операции статического импорта
мы можем использовать эти методы без названия класса. Например, писать не Math.sqrt(20), а sqrt(20), так как
функция sqrt(), которая возвращает квадратный корень числа, является статической. (Позже мы рассмотрим статические члены класса).
То же самое в отношении класса System: в нем определен статический объект out, поэтому мы можем его использовать без указания класса.
Все члены класса в языке Java - поля и методы - имеют модификаторы доступа. В прошлых темах мы уже сталкивались с модификатором
public. Модификаторы доступа позволяют задать допустимую область видимости для членов класса, то есть контекст, в котором можно
употреблять данную переменную или метод.
В Java используются следующие модификаторы доступа:
public: публичный, общедоступный класс или член класса. Поля и методы, объявленные с модификатором public, видны другим классам из текущего пакета и из внешних пакетов.
private: закрытый класс или член класса, противоположность модификатору public. Закрытый класс или член класса доступен только из кода в том же классе.
protected: такой класс или член класса доступен из любого места в текущем классе или пакете или в производных классах, даже если они находятся в других пакетах
Модификатор по умолчанию. Отсутствие модификатора у поля или метода класса предполагает применение к нему модификатора по умолчанию. Такие поля или методы видны всем классам в текущем пакете.
Рассмотрим модификаторы доступа на примере следующей программы:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 | public class Program{ public static void main(String[] args) { Person kate = new Person("Kate", 32, "Baker Street", "+12334567"); kate.displayName(); // норм, метод public kate.displayAge(); // норм, метод имеет модификатор по умолчанию kate.displayPhone(); // норм, метод protected //kate.displayAddress(); // ! Ошибка, метод private System.out.println(kate.name); // норм, модификатор по умолчанию System.out.println(kate.address); // норм, модификатор public System.out.println(kate.age); // норм, модификатор protected //System.out.println(kate.phone); // ! Ошибка, модификатор private }}class Person{ String name; protected int age; public String address; private String phone; public Person(String name, int age, String address, String phone){ this.name = name; this.age = age; this.address = address; this.phone = phone; } public void displayName(){ System.out.printf("Name: %s \n", name); } void displayAge(){ System.out.printf("Age: %d \n", age); } private void displayAddress(){ System.out.printf("Address: %s \n", address); } protected void displayPhone(){ System.out.printf("Phone: %s \n", phone); }} |
В данном случае оба класса расположены в одном пакете - пакете по умолчанию, поэтому в классе Program мы можем использовать все методы и переменные класса Person, которые имеют модификатор по умолчанию, public и protected. А поля и методы с модификатором private в классе Program не будут доступны.
Если бы класс Program располагался бы в другом пакете, то ему были бы доступны только поля и методы с модификатором public.
Модификатор доступа должен предшествовать остальной части определения переменной или метода.
Инкапсуляция
Казалось бы, почему бы не объявить все переменные и методы с модификатором public, чтобы они были доступны в любой точке программы вне зависимости от пакета или класса?
Возьмем, например, поле age, которое представляет возраст. Если другой класс имеет прямой доступ к этому полю, то есть вероятность, что в процессе работы
программы ему будет передано некорректное значение, например, отрицательное число. Подобное изменение данных не является желательным. Либо же мы хотим, чтобы некоторые данные были достуны напрямую,
чтобы их можно было вывести на консоль или просто узнать их значение. В этой связи рекомендуется
как можно больше ограничивать доступ к данным, чтобы защитить их от нежелательного доступа извне (как для получения значения, так и для его изменения).
Использование различных модификаторов гарантирует, что данные не будут искажены или изменены не надлежащим образом. Подобное сокрытие данных внутри некоторой области видимости
называется инкапсуляцией.
Так, как правило, вместо непосредственного применения полей используют методы доступа. Например:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 | public class Program{ public static void main(String[] args) { Person kate = new Person("Kate", 30); System.out.println(kate.getAge()); // 30 kate.setAge(33); System.out.println(kate.getAge()); // 33 kate.setAge(123450); System.out.println(kate.getAge()); // 33 }}class Person{ private String name; private int age = 1; public Person(String name, int age){ setName(name); setAge(age); } public String getName(){ return this.name; } public void setName(String name){ this.name = name; } public int getAge(){ return this.age; } public void setAge(int age){ if(age > 0 && age < 110) this.age = age; }} |
И затем вместо непосредственной работы с полями name и age в классе Person мы будем работать с методами, которые устанавливают и возвращают значения этих полей. Методы setName, setAge и наподобие еще называют мьютейтерами (mutator), так как они изменяют значения поля. А методы getName, getAge и наподобие называют аксессерами (accessor), так как с их помощью мы получаем значение поля.
Причем в эти методы мы можем вложить дополнительную логику. Например, в данном случае при изменении возраста производится проверка, насколько соответствует новое значение допустимому диапазону.
Кроме обычных методов и полей класс может иметь статические поля, методы, константы и инициализаторы. Например, главный класс программы имеет метод main, который является статическим:
1 2 3 | public static void main(String[] args) { } |
Для объявления статических переменных, констант, методов и инициализаторов перед их объявлением указывается ключевое слово static.
Статические поля
При создании объектов класса для каждого объекта создается своя копия нестатических обычных полей. А статические поля являются общими для всего класса. Поэтому они могут использоваться без создания объектов класса.
Например, создадим статическую переменную:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 | public class Program{ public static void main(String[] args) { Person tom = new Person(); Person bob = new Person(); tom.displayId(); // Id = 1 bob.displayId(); // Id = 2 System.out.println(Person.counter); // 3 // изменяем Person.counter Person.counter = 8; Person sam = new Person(); sam.displayId(); // Id = 8 }}class Person{ private int id; static int counter=1; Person(){ id = counter++; } public void displayId(){ System.out.printf("Id: %d \n", id); }} |
Класс Person содержит статическую переменную counter, которая увеличивается в конструкторе и ее значение присваивается переменной id. То есть при создании каждого нового объекта Person эта переменная будет увеличиваться, поэтому у каждого нового объекта Person значение поля id будет на 1 больше чем у предыдущего.
Так как переменная counter статическая, то мы можем обратиться к ней в программе по имени класса:
1 2 | System.out.println(Person.counter); // получаем значениеPerson.counter = 8; // изменяем значение |
Консольный вывод программы:
Id = 1 Id = 2 3 Id = 8
Статические константы
Также статическими бывают константы, которые являются общими для всего класса.
1 2 3 4 5 6 7 8 9 10 11 12 | public class Program{ public static void main(String[] args) { double radius = 60; System.out.printf("Radisu: %f \n", radius); // 60 System.out.printf("Area: %f \n", Math.PI * radius); // 188,4 }}class Math{ public static final double PI = 3.14;} |
Стоит отметить, что на протяжении всех предыдущих тем уже активно использовались статические константы. В частности, в выражении:
1 | System.out.println("hello"); |
out как раз представляет статическую константу класса System. Поэтому обращение к ней идет без создания объекта класса System.
Статические инициализаторы
Статические инициализаторы предназначены для инициализации статических переменных, либо для выполнения таких действий, которые выполняются при создании самого первого объекта. Например, определим статический инициализатор:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 | public class Program{ public static void main(String[] args) { Person tom = new Person(); Person bob = new Person(); tom.displayId(); // Id = 105 bob.displayId(); // Id = 106 }}class Person{ private int id; static int counter; static{ counter = 105; System.out.println("Static initializer"); } Person(){ id=counter++; System.out.println("Constructor"); } public void displayId(){ System.out.printf("Id: %d \n", id); }} |
Статический инициализатор определяется как обычный, только перед ним ставится ключевое слово static. В данном случае в статическом инициализаторе
мы устанавливаем начальное значение статического поля counter и выводим на консоль сообщение.
В самой программе создаются два объекта класса Person. Поэтому консольный вывод будет выглядеть следующим образом:
Static initializer Constructor Constructor Id: 105 Id: 106
Стоит учитывать, что вызов статического инициализатора производится после загрузки класса и фактически до создания самого первого объекта класса.
Статические методы
Статические методы также относятся ко всему классу в целом. Например, в примере выше статическая переменная counter была доступна извне, и мы могли изменить ее значение вне класса Person. Сделаем ее недоступной для изменения извне, но доступной для чтения. Для этого используем статический метод:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 | public class Program{ public static void main(String[] args) { Person.displayCounter(); // Counter: 1 Person tom = new Person(); Person bob = new Person(); Person.displayCounter(); // Counter: 3 }}class Person{ private int id; private static int counter = 1; Person(){ id = counter++; } // статический метод public static void displayCounter(){ System.out.printf("Counter: %d \n", counter); } public void displayId(){ System.out.printf("Id: %d \n", id); }} |
Теперь статическая переменная недоступна извне, она приватная. А ее значение выводится с помощью статического метода displayCounter. Для обращения к
статическому методу используется имя класса: Person.displayCounter().
При использовании статических методов надо учитывать ограничения: в статических методах мы можем вызывать только другие статические методы и использовать только статические переменные.
Вообще методы определяются как статические, когда методы не затрагиют состояние объекта, то есть его нестатические поля и константы, и для вызова метода нет смысла создавать экземпляр класса. Например:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 | public class Program{ public static void main(String[] args) { System.out.println(Operation.sum(45, 23)); // 68 System.out.println(Operation.subtract(45, 23)); // 22 System.out.println(Operation.multiply(4, 23)); // 92 }}class Operation{ static int sum(int x, int y){ return x + y; } static int subtract(int x, int y){ return x - y; } static int multiply(int x, int y){ return x * y; }} |
В данном случае для методов sum, subtract, multiply не имеет значения, какой именно экземпляр класса Operation используется. Эти методы работают только с параметрами, не затрагивая состояние класса. Поэтому их можно определить как статические.
Объекты классов, как и данные примитивных типов, могут передаваться в методы. Однако в данном случае есть одна особенность - при передаче объектов в качестве значения передается копия ссылки на область в памяти, где расположен этот объект. Рассмотрим небольшой пример. Пусть у нас есть следующий класс Person:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 | public class Program{ public static void main(String[] args) { Person kate = new Person("Kate"); System.out.println(kate.getName()); // Kate changeName(kate); System.out.println(kate.getName()); // Alice } static void changeName(Person p){ p.setName("Alice"); }}class Person{ private String name; Person(String name){ this.name = name; } public void setName(String name){ this.name = name; } public String getName(){ return this.name; }} |
Здесь в метод changeName передается объект Person, у которого изменяется имя. Так как в метод будет передаваться копия ссылки на область памяти, в которой находится объект Person, то переменная kate и параметр p метода changeName будут указывать на один и тот же объект в памяти. Поэтому после выполнения метода у объекта kate, который передается в метод, будет изменено имя с "Kate" на "Alice".
От этого случая следует отличать другой случай:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 | public class Program{ public static void main(String[] args) { Person kate = new Person("Kate"); System.out.println(kate.getName()); // Kate changePerson(kate); System.out.println(kate.getName()); // Kate - изменения не произошло // kate хранит ссылку на старый объект } static void changePerson(Person p){ p = new Person("Alice"); // p указывает на новый объект p.setName("Ann"); } static void changeName(Person p){ p.setName("Alice"); }}class Person{ private String name; Person(String name){ this.name = name; } public void setName(String name){ this.name = name; } public String getName(){ return this.name; }} |
В метод changePerson также передается копия ссылки на объект Person. Однако в самом методе мы изменяем не отдельные значения объекта, а пересоздаем объект с помощью конструктора и оператора new. В результате в памяти будет выделено новое место для нового объекта Person, и ссылка на этот объект будет привоена параметру p:
1 2 3 4 | static void changePerson(Person p){ p = new Person("Alice"); // p указывает на новый объект p.setName("Ann"); // изменяется новый объект} |
То есть после создания нового объекта Person параметр p и переменная kate в методе main будут хранить ссылки на разные объекты. Переменная kate, которая передавалась в метод, продолжит хранить ссылку на старый объект в памяти. Поэтому ее значение не меняется.
Классы могут быть вложенными (nested), то есть могут быть определены внутри других классов. Частным случаем вложенных классов являются внутренние классы (inner class). Например, имеется класс Person, внутри которого определен класс Account:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 | public class Program{ public static void main(String[] args) { Person tom = new Person("Tom", "qwerty"); tom.displayPerson(); tom.account.displayAccount(); }}class Person{ private String name; Account account; Person(String name, String password){ this.name = name; account = new Account(password); } public void displayPerson(){ System.out.printf("Person \t Name: %s \t Password: %s \n", name, account.password); } public class Account{ private String password; Account(String pass){ this.password = pass; } void displayAccount(){ System.out.printf("Account Login: %s \t Password: %s \n", Person.this.name, password); } }} |
Внутренний класс ведет себя как обычный класс за тем исключением, что его объекты могут быть созданы только внутри внешнего класса.
Внутренний класс имеет доступ ко всем полям внешнего класса, в том числе закрытым с помощью модификатора private. Аналогично внешний класс имеет доступ ко всем членам внутреннего класса, в том числе к полям и методам с модификатором private.
Ссылку на объект внешнего класса из внутреннего класса можно получить с помощью выражения Внешний_класс.this, например, Person.this.
Объекты внутренних классов могут быть созданы только в том классе, в котором внутренние классы опеределены. В других внешних классах объекты внутреннего класса создать нельзя.
Еще одной особенностью внутренних классов является то, что их можно объявить внутри любого контекста, в том числе внутри метода и даже в цикле:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 | public class Program{ public static void main(String[] args) { Person tom = new Person("Tom"); tom.setAccount("qwerty"); }}class Person{ private String name; Person(String name){ this.name = name; } public void setAccount (String password){ class Account{ void display(){ System.out.printf("Account Login: %s \t Password: %s \n", name, password); } } Account account = new Account(); account.display(); }} |
Статические вложенные классы
Кроме внутренних классов также могут быть статические вложенные классы. Статические вложенные классы позволяют скрыть некоторую комплексную информацию внутри внешнего класса:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 | class Math{ public static class Factorial{ private int result; private int key; public Factorial(int number, int x){ result=number; key = x; } public int getResult(){ return result; } public int getKey(){ return key; } } public static Factorial getFactorial(int x){ int result=1; for (int i = 1; i <= x; i++){ result *= i; } return new Factorial(result, x); }} |
Здесь определен вложенный класс для хранения данных о вычислении факториала. Основные действия выполняет метод getFactorial,
который возвращает объект вложенного класса. И теперь используем классы в методе main:
1 2 3 4 5 | public static void main(String[] args) { Math.Factorial fact = Math.getFactorial(6); System.out.printf("Факториал числа %d равен %d \n", fact.getKey(), fact.getResult());} |
Одним из ключевых аспектов объектно-ориентированного программирования является наследование. С помощью наследования можно расширить функционал уже имеющихся классов за счет добавления нового функционала или изменения старого. Например, имеется следующий класс Person, описывающий отдельного человека:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | class Person { String name; public String getName(){ return name; } public Person(String name){ this.name=name; } public void display(){ System.out.println("Name: " + name); }} |
И, возможно, впоследствии мы захотим добавить еще один класс, который описывает сотрудника предприятия - класс Employee. Так как этот класс реализует тот же функционал, что и класс Person, поскольку сотрудник - это также и человек, то было бы рационально сделать класс Employee производным (наследником, подклассом) от класса Person, который, в свою очередь, называется базовым классом, родителем или суперклассом:
1 2 3 4 5 6 | class Employee extends Person{ public Employee(String name){ super(name); // если базовый класс определяет конструктор // то производный класс должен его вызвать }} |
Чтобы объявить один класс наследником от другого, надо использовать после имени класса-наследника ключевое слово extends, после которого идет имя базового класса. Для класса Employee базовым является Person, и поэтому класс Employee наследует все те же поля и методы, которые есть в классе Person.
Если в базовом классе определены конструкторы, то в конструкторе производного классы необходимо вызвать один из конструкторов базового класса с
помощью ключевого слова super. Например, класс Person имеет конструктор, который принимает один параметр. Поэтому в классе
Employee в конструкторе нужно вызвать конструктор класса Person. То есть вызов super(name) будет представлять вызов конструктора класса Person.
При вызове конструктора после слова super в скобках идет перечисление передаваемых аргументов.
При этом вызов конструктора базового класса должен идти в самом начале в конструкторе производного класса.
Таким образом, установка имени сотрудника делегируется конструктору базового класса.
Причем даже если производный класс никакой другой работы не производит в конструкторе, как в примере выше, все равно необходимо вызвать конструктор базового класса.
Использование классов:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 | public class Program{ public static void main(String[] args) { Person tom = new Person("Tom"); tom.display(); Employee sam = new Employee("Sam"); sam.display(); }}class Person { String name; public String getName(){ return name; } public Person(String name){ this.name=name; } public void display(){ System.out.println("Name: " + name); }}class Employee extends Person{ public Employee(String name){ super(name); // если базовый класс определяет конструктор // то производный класс должен его вызвать }} |
Производный класс имеет доступ ко всем методам и полям базового класса (даже если базовый класс находится в другом пакете) кроме тех, которые определены с модификатором private. При этом производный класс также может добавлять свои поля и методы:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 | public class Program{ public static void main(String[] args) { Employee sam = new Employee("Sam", "Microsoft"); sam.display(); // Sam sam.work(); // Sam works in Microsoft }}class Person { String name; public String getName(){ return name; } public Person(String name){ this.name=name; } public void display(){ System.out.println("Name: " + name); }}class Employee extends Person{ String company; public Employee(String name, String company) { super(name); this.company=company; } public void work(){ System.out.printf("%s works in %s \n", getName(), company); }} |
В данном случае класс Employee добавляет поле company, которое хранит место работы сотрудника, а также метод work.
Переопределение методов
Производный класс может определять свои методы, а может переопределять методы, которые унаследованы от базового класса. Например, переопределим в классе Employee метод display:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 | public class Program{ public static void main(String[] args) { Employee sam = new Employee("Sam", "Microsoft"); sam.display(); // Sam // Works in Microsoft }}class Person { String name; public String getName(){ return name; } public Person(String name){ this.name=name; } public void display(){ System.out.println("Name: " + name); }}class Employee extends Person{ String company; public Employee(String name, String company) { super(name); this.company=company; } @Override public void display(){ System.out.printf("Name: %s \n", getName()); System.out.printf("Works in %s \n", company); }} |
Перед переопределяемым методом указывается аннотация @Override. Данная аннотация в принципе необязательна.
При переопределении метода он должен иметь уровень доступа не меньше, чем уровень доступа в базовом класса. Например, если в базовом классе метод имеет модификатор public, то и в производном классе метод должен иметь модификатор public.
Однако в данном случае мы видим, что часть метода display в Employee повторяет действия из метода display базового класса. Поэтому мы можем сократить класс Employee:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | class Employee extends Person{ String company; public Employee(String name, String company) { super(name); this.company=company; } @Override public void display(){ super.display(); System.out.printf("Works in %s \n", company); }} |
С помощью ключевого слова super мы также можем обратиться к реализации методов базового класса.
Запрет наследования
Хотя наследование очень интересный и эффективный механизм, но в некоторых ситуациях его применение может быть нежелательным. И в этом случае можно запретить наследование с помощью ключевого слова final. Например:
1 2 | public final class Person {} |
Если бы класс Person был бы определен таким образом, то следующий код был бы ошибочным и не сработал, так как мы тем самым запретили наследование:
1 2 | class Employee extends Person{ {} |
Кроме запрета наследования можно также запретить переопределение отдельных методов. Например, в примере выше переопределен метод display(),
запретим его переопределение:
1 2 3 4 5 6 7 8 9 | public class Person { //........................ public final void display(){ System.out.println("Имя: " + name); }} |
В этом случае класс Employee не сможет переопределить метод display.
Динамическая диспетчеризация методов
Наследование и возможность переопределения методов открывают нам большие возможности. Прежде всего мы можем передать переменной суперкласса ссылку на объект подкласса:
1 | Person sam = new Employee("Sam", "Oracle"); |
Так как Employee наследуется от Person, то объект Employee является в то же время и объектом Person. Грубо говоря, любой работник предприятия одновременно является человеком.
Однако несмотря на то, что переменная представляет объект Person, виртуальная машина видит, что в реальности она указывает на объект Employee. Поэтому при вызове методов у этого объекта будет вызываться та версия метода, которая определена в классе Employee, а не в Person. Например:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 | public class Program{ public static void main(String[] args) { Person tom = new Person("Tom"); tom.display(); Person sam = new Employee("Sam", "Oracle"); sam.display(); }}class Person { String name; public String getName() { return name; } public Person(String name){ this.name=name; } public void display(){ System.out.printf("Person %s \n", name); }}class Employee extends Person{ String company; public Employee(String name, String company) { super(name); this.company = company; } @Override public void display(){ System.out.printf("Employee %s works in %s \n", super.getName(), company); }} |
Консольный вывод данной программы:
Person Tom Employee Sam works in Oracle
При вызове переопределенного метода виртуальная машина динамически находит и вызывает именно ту версию метода, которая определена в подклассе. Данный процесс еще называется dynamic method lookup или динамический поиск метода или динамическая диспетчеризация методов.
Кроме обычных классов в Java есть абстрактные классы. Абстрактный класс похож на обычный класс. В абстрактном классе также можно определить поля и методы, но в то же время нельзя создать объект или экземпляр абстрактного класса. Абстрактные классы призваны предоставлять базовый функционал для классов-наследников. А производные классы уже реализуют этот функционал.
При определении абстрактных классов используется ключевое слово abstract:
1 2 3 4 5 6 | public abstract class Human{ private String name; public String getName() { return name; }} |
Но главное отличие состоит в том, что мы не можем использовать конструктор абстрактного класса для создания его объекта. Например, следующим образом:
1 | Human h = new Human(); |
Кроме обычных методов абстрактный класс может содержать абстрактные методы. Такие методы определяются с помощью
ключевого слова abstract и не имеют никакой реализации:
1 | public abstract void display(); |
Производный класс обязан переопределить и реализовать все абстрактные методы, которые имеются в базовом абстрактном классе. Также следует учитывать, что если класс имеет хотя бы один абстрактный метод, то данный класс должен быть определен как абстрактный.
Зачем нужны абстрактные классы? Допустим, мы делаем программу для обслуживания банковских операций и определяем в ней три класса: Person, который описывает человека, Employee, который описывает банковского служащего, и класс Client, который представляет клиента банка. Очевидно, что классы Employee и Client будут производными от класса Person, так как оба класса имеют некоторые общие поля и методы. И так как все объекты будут представлять либо сотрудника, либо клиента банка, то напрямую мы от класса Person создавать объекты не будем. Поэтому имеет смысл сделать его абстрактным.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 | public class Program{ public static void main(String[] args) { Employee sam = new Employee("Sam", "Leman Brothers"); sam.display(); Client bob = new Client("Bob", "Leman Brothers"); bob.display(); }}abstract class Person { private String name; public String getName() { return name; } public Person(String name){ this.name=name; } public abstract void display();}class Employee extends Person{ private String bank; public Employee(String name, String company) { super(name); this.bank = company; } public void display(){ System.out.printf("Employee Name: %s \t Bank: %s \n", super.getName(), bank); }}class Client extends Person{ private String bank; public Client(String name, String company) { super(name); this.bank = company; } public void display(){ System.out.printf("Client Name: %s \t Bank: %s \n", super.getName(), bank); }} |
Другим хрестоматийным примером является система геометрических фигур. В реальности не существует геометрической фигуры как таковой. Есть круг, прямоугольник, квадрат, но просто фигуры нет. Однако же и круг, и прямоугольник имеют что-то общее и являются фигурами:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 | // абстрактный класс фигурыabstract class Figure{ float x; // x-координата точки float y; // y-координата точки Figure(float x, float y){ this.x=x; this.y=y; } // абстрактный метод для получения периметра public abstract float getPerimeter(); // абстрактный метод для получения площади public abstract float getArea();}// производный класс прямоугольникаclass Rectangle extends Figure{ private float width; private float height; // конструктор с обращением к конструктору класса Figure Rectangle(float x, float y, float width, float height){ super(x,y); this.width = width; this.height = height; } public float getPerimeter(){ return width * 2 + height * 2; } public float getArea(){ return width * height; }} |
В прошлой главе говорилось о преобразованиях объектов простых типов. Однако с объектами классов все происходит немного по-другому. Допустим, у нас есть следующая иерархия классов:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 | public class Program{ public static void main(String[] args) { Person tom = new Person("Tom"); tom.display(); Person sam = new Employee("Sam", "Oracle"); sam.display(); Person bob = new Client("Bob", "DeutscheBank", 3000); bob.display(); }}// класс человекаclass Person { private String name; public String getName() { return name; } public Person(String name){ this.name=name; } public void display(){ System.out.printf("Person %s \n", name); }}// служащий некоторой компании class Employee extends Person{ private String company; public Employee(String name, String company) { super(name); this.company = company; } public String getCompany(){ return company; } public void display(){ System.out.printf("Employee %s works in %s \n", super.getName(), company); }}// класс клиента банкаclass Client extends Person{ private int sum; // Переменная для хранения суммы на счете private String bank; public Client(String name, String bank, int sum) { super(name); this.bank=bank; this.sum=sum; } public void display(){ System.out.printf("Client %s has account in %s \n", super.getName(), bank); } public String getBank(){ return bank; } public int getSum(){ return sum; }} |
В этой иерархии классов можно проследить следующую цепь наследования: Object (все классы неявно наследуются от типа Object) -> Person -> Employee|Client.
Суперклассы обычно размещаются выше подклассов, поэтому на вершине наследования находится класс Object, а в самом низу Employee и Client.
Объект подкласса также представляет объект суперкласса. Поэтому в программе мы можем написать следующим образом:
1 2 3 4 5 | Object tom = new Person("Tom");Object sam = new Employee("Sam", "Oracle");Object kate = new Client("Kate", "DeutscheBank", 2000);Person bob = new Client("Bob", "DeutscheBank", 3000);Person alice = new Employee("Alice", "Google"); |
Это так называемое восходящее преобразование (от подкласса внизу к суперклассу вверху иерархии) или upcasting. Такое преобразование осуществляется автоматически.
Обратное не всегда верно. Например, объект Person не всегда является объектом Employee или Client. Поэтому нисходящее преобразование или downcasting от суперкласса к подклассу автоматически не выполняется. В этом случае нам надо использовать операцию преобразования типов.
1 2 3 4 5 6 | Object sam = new Employee("Sam", "Oracle"); // нисходящее преобразование от Object к типу EmployeeEmployee emp = (Employee)sam;emp.display();System.out.println(emp.getCompany()); |
В данном случае переменная sam приводится к типу Employee. И затем через объект emp мы можем обратиться к функционалу объекта Employee.
Мы можем преобразовать объект Employee по всей прямой линии наследования от Object к Employee.
Примеры нисходящих перобразований:
1 2 3 4 5 | Object kate = new Client("Kate", "DeutscheBank", 2000);((Person)kate).display(); Object sam = new Employee("Sam", "Oracle");((Employee)sam).display(); |
Но рассмотрим еще одну ситуацию:
1 2 3 4 5 6 | Object kate = new Client("Kate", "DeutscheBank", 2000);Employee emp = (Employee) kate;emp.display(); // или так((Employee)kate).display(); |
В данном случае переменная типа Object хранит ссылку на объект Client. Мы можем без ошибок привести этот объект к типам Person или Client. Но при попытке преобразования к типу Employee мы получим ошибку во время выполнения. Так как kate не представляет объект типа Employee.
Оператор instanceof
В примере выше мы явно видим, что переменная kate - это ссылка на объект Client, а не Employee. Однако нередко данные приходят извне, и мы можем точно не знать, какой именно объект эти данные представляют. Соответственно возникает большая вероятность столкнуться с ошибкой. И перед тем, как провести преобразование типов, мы можем проверить, а можем ли мы выполнить приведение с помощью оператора instanceof:
1 2 3 4 5 6 7 8 9 10 | Object kate = new Client("Kate", "DeutscheBank", 2000);if(kate instanceof Employee){ Employee employeeKate = (Employee) kate; employeeKate.display();}else{ System.out.println("Conversion is invalid");} |
Выражение kate instanceof Employee проверяет, является ли переменная kate объектом типа Employee. Но так как в данном случае явно
не является, то такая проверка вернет значение false, и преобразование не сработает.
А выражение kate instanceof Client возвратило бы true:
1 2 3 4 5 6 7 8 9 10 | Object kate = new Client("Kate", "DeutscheBank", 2000);if(kate instanceof Client){ Client clientKate = (Client) kate; clientKate.display();}else{ System.out.println("Conversion is invalid");} |
Следует отметить, что начиная с версии Java 16 мы можем упростить преобразование типов следующим образом:
1 2 3 4 5 6 7 8 9 | Object kate = new Client("Kate", "DeutscheBank", 2000);if(kate instanceof Client clientKate){ clientKate.display();}else{ System.out.println("Conversion is invalid");} |
Выражение
1 | kate instanceof Client clientKate |
Проверяет, представляет ли переменная kate класс Client, и если представляет (то есть оператор instanceof
возвращает true), то создает переменную clientKate типа Client. И в дальнейшем мы можем использовать эту переменную clientKate и производить
с ней различные операции.
Механизм наследования очень удобен, но он имеет свои ограничения. В частности мы можем наследовать только от одного класса, в отличие, например, от языка С++, где имеется множественное наследование.
В языке Java подобную проблему частично позволяют решить интерфейсы. Интерфейсы определяют некоторый функционал, не имеющий конкретной реализации, который затем реализуют классы, применяющие эти интерфейсы. И один класс может применить множество интерфейсов.
Чтобы определить интерфейс, используется ключевое слово interface. Например:
1 2 3 4 | interface Printable{ void print();} |
Данный интерфейс называется Printable. Интерфейс может определять константы и методы, которые могут иметь, а могут и не иметь реализации. Методы без реализации похожи на абстрактные методы абстрактных классов. Так, в данном случае объявлен один метод, который не имеет реализации.
Все методы интерфейса не имеют модификаторов доступа, но фактически по умолчанию доступ public, так как цель интерфейса - определение функционала для реализации его классом. Поэтому весь функционал должен быть открыт для реализации.
Чтобы класс применил интерфейс, надо использовать ключевое слово implements:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 | public class Program{ public static void main(String[] args) { Book b1 = new Book("Java. Complete Referense.", "H. Shildt"); b1.print(); }}interface Printable{ void print();}class Book implements Printable{ String name; String author; Book(String name, String author){ this.name = name; this.author = author; } public void print() { System.out.printf("%s (%s) \n", name, author); }} |
В данном случае класс Book реализует интерфейс Printable. При этом надо учитывать, что если класс применяет интерфейс, то он должен реализовать все методы интерфейса, как в случае выше реализован метод print.
Потом в методе main мы можем создать объект класса Book и вызвать его метод print. Если класс не реализует какие-то методы интерфейса, то такой класс должен быть определен как абстрактный,
а его неабстрактные классы-наследники затем должны будут реализовать эти методы.
В тоже время мы не можем напрямую создавать объекты интерфейсов, поэтому следующий код не будет работать:
1 2 | Printable pr = new Printable();pr.print(); |
Одним из преимуществ использования интерфейсов является то, что они позволяют добавить в приложение гибкости. Например, в дополнение к классу Book определим еще один класс, который будет реализовывать интерфейс Printable:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | class Journal implements Printable { private String name; String getName(){ return name; } Journal(String name){ this.name = name; } public void print() { System.out.println(name); } } |
Класс Book и класс Journal связаны тем, что они реализуют интерфейс Printable. Поэтому мы динамически в программе можем создавать объекты Printable как экземпляры обоих классов:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 | public class Program{ public static void main(String[] args) { Printable printable = new Book("Java. Complete Reference", "H. Shildt"); printable.print(); // Java. Complete Reference (H. Shildt) printable = new Journal("Foreign Policy"); printable.print(); // Foreign Policy }}interface Printable{ void print();}class Book implements Printable{ String name; String author; Book(String name, String author){ this.name = name; this.author = author; } public void print() { System.out.printf("%s (%s) \n", name, author); }}class Journal implements Printable { private String name; String getName(){ return name; } Journal(String name){ this.name = name; } public void print() { System.out.println(name); } } |
Интерфейсы в преобразованиях типов
Все сказанное в отношении преобразования типов характерно и для интерфейсов. Например, так как класс Journal реализует интерфейс Printable, то переменная типа Printable может хранить ссылку на объект типа Journal:
1 2 3 4 5 | Printable p =new Journal("Foreign Affairs");p.print(); // Интерфейс не имеет метода getName, необходимо явное приведениеString name = ((Journal)p).getName();System.out.println(name); |
И если мы хотим обратиться к методам класса Journal, которые определены не в интерфейсе Printable, а в самом классе Journal, то нам надо
явным образом выполнить преобразование типов: ((Journal)p).getName();
Методы по умолчанию
Ранее до JDK 8 при реализации интерфейса мы должны были обязательно реализовать все его методы в классе. А сам интерфейс мог содержать только определения методов без конкретной реализации. В JDK 8 была добавлена такая функциональность как методы по умолчанию. И теперь интерфейсы кроме определения методов могут иметь их реализацию по умолчанию, которая используется, если класс, реализующий данный интерфейс, не реализует метод. Например, создадим метод по умолчанию в интерфейсе Printable:
1 2 3 4 5 6 7 | interface Printable { default void print(){ System.out.println("Undefined printable"); }} |
Метод по умолчанию - это обычный метод без модификаторов, который помечается ключевым словом default. Затем в классе Journal нам необязательно этот метод реализовать, хотя мы можем его и переопределить:
1 2 3 4 5 6 7 8 9 10 11 12 | class Journal implements Printable { private String name; String getName(){ return name; } Journal(String name){ this.name = name; }} |
Статические методы
Начиная с JDK 8 в интерфейсах доступны статические методы - они аналогичны методам класса:
1 2 3 4 5 6 7 8 9 | interface Printable { void print(); static void read(){ System.out.println("Read printable"); }} |
Чтобы обратиться к статическому методу интерфейса также, как и в случае с классами, пишут название интерфейса и метод:
1 2 3 4 | public static void main(String[] args) { Printable.read();} |
Приватные методы
По умолчанию все методы в интерфейсе фактически имеют модификатор public. Однако начиная с Java 9 мы также можем определять в интерфейсе методы с модификатором private. Они могут быть статическими и нестатическими, но они не могут иметь реализации по умолчанию.
Подобные методы могут использоваться только внутри самого интерфейса, в котором они определены. То есть к примеру нам надо выполнять в интерфейсе некоторые повторяющиеся действия, и в этом случае такие действия можно выделить в приватные методы:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 | public class Program{ public static void main(String[] args) { Calculatable c = new Calculation(); System.out.println(c.sum(1, 2)); System.out.println(c.sum(1, 2, 4)); }}class Calculation implements Calculatable{ }interface Calculatable{ default int sum(int a, int b){ return sumAll(a, b); } default int sum(int a, int b, int c){ return sumAll(a, b, c); } private int sumAll(int... values){ int result = 0; for(int n : values){ result += n; } return result; }} |
Константы в интерфейсах
Кроме методов в интерфейсах могут быть определены статические константы:
1 2 3 4 5 6 7 | interface Stateable{ int OPEN = 1; int CLOSED = 0; void printState(int n);} |
Хотя такие константы также не имеют модификаторов, но по умолчанию они имеют модификатор доступа public static final,
и поэтому их значение доступно из любого места программы.
Применение констант:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 | public class Program{ public static void main(String[] args) { WaterPipe pipe = new WaterPipe(); pipe.printState(1); }}class WaterPipe implements Stateable{ public void printState(int n){ if(n==OPEN) System.out.println("Water is opened"); else if(n==CLOSED) System.out.println("Water is closed"); else System.out.println("State is invalid"); }}interface Stateable{ int OPEN = 1; int CLOSED = 0; void printState(int n);} |
Множественная реализация интерфейсов
Если нам надо применить в классе несколько интерфейсов, то они все перечисляются через запятую после слова implements:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | interface Printable { // методы интерфейса}interface Searchable { // методы интерфейса}class Book implements Printable, Searchable{ // реализация класса} |
Наследование интерфейсов
Интерфейсы, как и классы, могут наследоваться:
1 2 3 4 | interface BookPrintable extends Printable{ void paint();} |
При применении этого интерфейса класс Book должен будет реализовать как методы интерфейса BookPrintable, так и методы базового интерфейса Printable.
Вложенные интерфейсы
Как и классы, интерфейсы могут быть вложенными, то есть могут быть определены в классах или других интерфейсах. Например:
1 2 3 4 5 6 | class Printer{ interface Printable { void print(); }} |
При применении такого интерфейса нам надо указывать его полное имя вместе с именем класса:
1 2 3 4 5 6 7 8 9 10 11 12 | public class Journal implements Printer.Printable { String name; Journal(String name){ this.name = name; } public void print() { System.out.println(name); } } |
Использование интерфейса будет аналогично предыдущим случаям:
1 2 | Printer.Printable p =new Journal("Foreign Affairs");p.print(); |
Интерфейсы как параметры и результаты методов
И также как и в случае с классами, интерфейсы могут использоваться в качестве типа параметров метода или в качестве возвращаемого типа:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 | public class Program{ public static void main(String[] args) { Printable printable = createPrintable("Foreign Affairs",false); printable.print(); read(new Book("Java for impatients", "Cay Horstmann")); read(new Journal("Java Dayly News")); } static void read(Printable p){ p.print(); } static Printable createPrintable(String name, boolean option){ if(option) return new Book(name, "Undefined"); else return new Journal(name); }}interface Printable{ void print();}class Book implements Printable{ String name; String author; Book(String name, String author){ this.name = name; this.author = author; } public void print() { System.out.printf("%s (%s) \n", name, author); }}class Journal implements Printable { private String name; String getName(){ return name; } Journal(String name){ this.name = name; } public void print() { System.out.println(name); } } |
Метод read() в качестве параметра принимает объект интерфейса Printable, поэтому в этот метод мы можем передать как объект Book, так
и объект Journal.
Метод createPrintable() возвращает объект Printable, поэтому также мы можем возвратить как объект Book, так и Journal.
Консольный вывод:
Foreign Affairs Java for impatients (Cay Horstmann) Java Dayly News
Одним из распространенных способов использования интерфейсов в Java является создание обратного вызова. Суть обратного вызова состоит в том, что мы создаем действия, которые вызываются при других действиях. То есть одни действия вызываются другими действиями. Стандартный пример - нажатие на кнопку. Когда мы нажимаем на кнопку, мы производим действие, но в ответ на это нажатие запускаются другие действия. Например, нажатие на значок принтера запускает печать документа на принтере и т.д.
Рассмотрим следующий пример:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 | public class EventsApp { public static void main(String[] args) { Button button = new Button(new ButtonClickHandler()); button.click(); button.click(); button.click(); }}class ButtonClickHandler implements EventHandler{ public void execute(){ System.out.println("Кнопка нажата!"); }}interface EventHandler{ void execute();}class Button{ EventHandler handler; Button(EventHandler action){ this.handler=action; } public void click(){ handler.execute(); }} |
Итак, здесь у нас определен класс Button, который в конструкторе принимает объект интерфейса EventHandler и в методе click (имитация нажатия) вызывает метод execute этого объекта.
Далее определяется реализация EventHandler в виде класса ButtonClickHandler. И в основной программе объект этого класса передается в конструктор Button.
Таким образом, через конструктор мы устанавливаем обработчик нажатия кнопки. И при каждом вызове метода button.click() будет вызываться этот обработчик.
В итоге программа выведет на консоль следующий результат:
Кнопка нажата! Кнопка нажата! Кнопка нажата!
Но казалось бы, зачем нам выносить все действия в интерфейс, его реализовать, почему бы не написать проще сразу в классе Button:
1 2 3 4 5 6 7 | class Button{ public void click(){ System.out.println("Кнопка нажата!"); }} |
Дело в том, что на момент определения класса нам не всегда бывают точно известны те действия, которые должны производиться. Особенно если класс Button и класс основной программы находятся в разных пакетах, библиотеках и могут проектироваться разными разработчиками. К тому же у нас может быть несколько кнопок - объектов Button и для каждого объекта надо определить свое действие. Например, изменим главный класс программы:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 | public class EventsApp { public static void main(String[] args) { Button tvButton = new Button(new EventHandler(){ private boolean on = false; public void execute(){ if(on) { System.out.println("Телевизор выключен.."); on=false; } else { System.out.println("Телевизор включен!"); on=true; } } }); Button printButton = new Button(new EventHandler(){ public void execute(){ System.out.println("Запущена печать на принтере..."); } }); tvButton.click(); printButton.click(); tvButton.click(); }} |
Здесь у нас две кнопки - одна для включения-выключения телевизора, а другая для печати на принтере. Вместо того, чтобы создавать отдельные
классы, реализующие интерфейс EventHandler, здесь обработчики задаются в виде анонимных объектов, которые реализуют интерфейс EventHandler. Причем обработчик
кнопки телевизора хранит дополнительное состояние в виде логической переменной on.
В итоге консоль выведет нам следующий результат:
Телевизор включен! Запущена печать на принтере... Телевизор выключен..
И в завершении надо сказать, что интерфейсы в данном качестве особенно широко используются в различных графических API - AWT, Swing, JavaFX, где обработка событий объектов - элементов графического интерфейса особенно актуальна.
Кроме отдельных примитивных типов данных и классов в Java есть такой тип как enum или перечисление. Перечисления представляют набор логически связанных констант. Объявление перечисления происходит с помощью оператора enum, после которого идет название перечисления. Затем идет список элементов перечисления через запятую:
1 2 3 4 5 6 7 8 9 10 | enum Day{ MONDAY, TUESDAY, WEDNESDAY, THURSDAY, FRIDAY, SATURDAY, SUNDAY} |
Перечисление фактически представляет новый тип, поэтому мы можем определить переменную данного типа и использовать ее:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 | public class Program{ public static void main(String[] args) { Day current = Day.MONDAY; System.out.println(current); // MONDAY }}enum Day{ MONDAY, TUESDAY, WEDNESDAY, THURSDAY, FRIDAY, SATURDAY, SUNDAY} |
Перечисления могут использоваться в классах для хранения данных:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 | public class Program{ public static void main(String[] args) { Book b1 = new Book("War and Peace", "L. Tolstoy", Type.BELLETRE); System.out.printf("Book '%s' has a type %s \n", b1.name, b1.getType()); }}class Book{ private Type bookType; String name; String author; Book(String name, String author, Type type){ this.bookType = type; this.name = name; this.author = author; } String getType(){ switch(bookType){ case BELLETRE: return "Belletre"; case SCIENCE: return "Science"; case SCIENCE_FICTION: return "Science fiction"; case PHANTASY: return "Phantasy"; default: return "Undefined"; } }} enum Type{ SCIENCE, BELLETRE, PHANTASY, SCIENCE_FICTION} |
Само перечисление объявлено вне класса, оно содержит четыре жанра книг. Класс Book кроме обычных переменных содержит также переменную типа нашего перечисления. В конструкторе мы ее также можем присвоить, как и обычные поля класса.
С помощью конструкции switch..case можно проверить принадлежность значения bookType определенной константе перечисления. Пример работы программы:
Book 'War and Peace' has a type Belletre
Методы перечислений
Каждое перечисление имеет статический метод values(). Он возвращает массив всех констант перечисления:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | public class Program{ public static void main(String[] args) { Type[] types = Type.values(); for (Type s : types) { System.out.println(s); } }}enum Type{ SCIENCE, BELLETRE, PHANTASY, SCIENCE_FICTION} |
Метод ordinal() возвращает порядковый номер определенной константы (нумерация начинается с 0):
1 | System.out.println(Type.BELLETRE.ordinal()); // 1 |
Конструкторы, поля и методы перечисления
Перечисления, как и обычные классы, могут определять конструкторы, поля и методы. Например:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 | public class Program{ public static void main(String[] args) { System.out.println(Color.RED.getCode()); // #FF0000 System.out.println(Color.GREEN.getCode()); // #00FF00 }}enum Color{ RED("#FF0000"), BLUE("#0000FF"), GREEN("#00FF00"); private String code; Color(String code){ this.code = code; } public String getCode(){ return code;}} |
Перечисление Color определяет приватное поле code для хранения кода цвета, а с помощью метода getCode оно возвращается. Через конструктор передается для него значение. Следует отметить, что конструктор по умолчанию приватный, то есть имеет модификатор private. Любой другой модификатор будет считаться ошибкой. Поэтому создать константы перечисления с помощью конструктора мы можем только внутри перечисления.
Также можно определять методы для отдельных констант:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 | public class Program{ public static void main(String[] args) { Operation op = Operation.SUM; System.out.println(op.action(10, 4)); // 14 op = Operation.MULTIPLY; System.out.println(op.action(6, 4)); // 24 }}enum Operation{ SUM{ public int action(int x, int y){ return x + y;} }, SUBTRACT{ public int action(int x, int y){ return x - y;} }, MULTIPLY{ public int action(int x, int y){ return x * y;} }; public abstract int action(int x, int y);} |
Хотя мы можем создать обычный класс, который не является наследником, но фактически все классы наследуются от класса Object. Все остальные классы, даже те, которые мы добавляем в свой проект, являются неявно производными от класса Object. Поэтому все типы и классы могут реализовать те методы, которые определены в классе Object. Рассмотрим эти методы.
toString
Метод toString служит для получения представления данного объекта в виде строки. При попытке вывести строковое представления
какого-нибудь объекта, как правило, будет выводиться полное имя класса. Например:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | public class Program{ public static void main(String[] args) { Person tom = new Person("Tom"); System.out.println(tom.toString()); // Будет выводить что-то наподобие Person@7960847b }}class Person { private String name; public Person(String name){ this.name=name; }} |
Полученное мной значение (в данном случае Person@7960847b) вряд ли может служить хорошим строковым описанием объекта.
Поэтому метод toString() нередко переопределяют. Например:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 | public class Program{ public static void main(String[] args) { Person tom = new Person("Tom"); System.out.println(tom.toString()); // Person Tom }}class Person { private String name; public Person(String name){ this.name=name; } @Override public String toString(){ return "Person " + name; }} |
Метод hashCode
Метод hashCode позволяет задать некоторое числовое значение, которое будет соответствовать данному объекту или его хэш-код. По данному числу, например, можно сравнивать объекты.
Например, выведем представление вышеопределенного объекта:
1 2 | Person tom = new Person("Tom");System.out.println(tom.hashCode()); // 2036368507 |
Но мы можем задать свой алгоритм определения хэш-кода объекта:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | class Person { private String name; public Person(String name){ this.name=name; } @Override public int hashCode(){ return 10 * name.hashCode() + 20456; }} |
Получение типа объекта и метод getClass
Метод getClass позволяет получить тип данного объекта:
1 2 | Person tom = new Person("Tom");System.out.println(tom.getClass()); // class Person |
Метод equals
Метод equals сравнивает два объекта на равенство:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 | public class Program{ public static void main(String[] args) { Person tom = new Person("Tom"); Person bob = new Person("Bob"); System.out.println(tom.equals(bob)); // false Person tom2 = new Person("Tom"); System.out.println(tom.equals(tom2)); // true }}class Person { private String name; public Person(String name){ this.name=name; } @Override public boolean equals(Object obj){ if (!(obj instanceof Person)) return false; Person p = (Person)obj; return this.name.equals(p.name); }} |
Метод equals принимает в качестве параметра объект любого типа, который мы затем приводим к текущему, если они являются объектами одного класса.
Оператор instanceof позволяет выяснить, является ли переданный в качестве параметра объект объектом определенного класса, в данном случае класса Person. Если объекты принадлежат к разным классам, то их сравнение не имеет смысла, и возвращается значение false.
Затем сравниваем по именам. Если они совпадают, возвращаем true, что будет говорить, что объекты равны.
Обобщения или generics (обобщенные типы и методы) позволяют нам уйти от жесткого определения используемых типов. Рассмотрим проблему, в которой они нам могут понадобиться.
Допустим, мы определяем класс для представления банковского счета. К примеру, он мог бы выглядеть следующим образом:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | class Account{ private int id; private int sum; Account(int id, int sum){ this.id = id; this.sum = sum; } public int getId() { return id; } public int getSum() { return sum; } public void setSum(int sum) { this.sum = sum; }} |
Класс Account имеет два поля: id - уникальный идентификатор счета и sum - сумма на счете.
В данном случае идентификатор задан как целочисленное значение, например, 1, 2, 3, 4 и так далее. Однако также нередко для идентификатора используются и строковые значения. И числовые, и строковые значения имеют свои плюсы и минусы. И на момент написания класса мы можем точно не знать, что лучше выбрать для хранения идентификатора - строки или числа. Либо, возможно, этот класс будет использоваться другими разработчиками, которые могут иметь свое мнение по данной проблеме. Например, в качестве типа id они захотят использовать какой-то свой класс.
И на первый взгляд мы можем решить данную проблему следующим образом: задать id как поле типа Object, который является универсальным и базовым суперклассом для всех остальных типов:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 | public class Program{ public static void main(String[] args) { Account acc1 = new Account(2334, 5000); // id - число int acc1Id = (int)acc1.getId(); System.out.println(acc1Id); Account acc2 = new Account("sid5523", 5000); // id - строка System.out.println(acc2.getId()); }}class Account{ private Object id; private int sum; Account(Object id, int sum){ this.id = id; this.sum = sum; } public Object getId() { return id; } public int getSum() { return sum; } public void setSum(int sum) { this.sum = sum; }} |
В данном случае все замечательно работает. Однако тогда мы сталкиваемся с проблемой безопасности типов. Например, в следующем случае мы получим ошибку:
1 2 3 | Account acc1 = new Account("2345", 5000);int acc1Id = (int)acc1.getId(); // java.lang.ClassCastExceptionSystem.out.println(acc1Id); |
Проблема может показаться искуственной, так как в данном случае мы видим, что в конструктор передается строка, поэтому мы вряд ли будем пытаться преобразовывать ее к типу int. Однако в процессе разработки мы можем не знать, какой именно тип представляет значение в id, и при попытке получить число в данном случае мы столкнемся с исключением java.lang.ClassCastException.
Писать для каждого отдельного типа свою версию класса Account тоже не является хорошим решением, так как в этом случае мы вынуждены повторяться.
Эти проблемы были призваны устранить обобщения или generics. Обобщения позволяют не указывать конкретный тип, который будет использоваться. Поэтому определим класс Account как обобщенный:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | class Account<T>{ private T id; private int sum; Account(T id, int sum){ this.id = id; this.sum = sum; } public T getId() { return id; } public int getSum() { return sum; } public void setSum(int sum) { this.sum = sum; }} |
С помощью буквы T в определении класса class Account<T> мы указываем, что данный тип
T будет использоваться этим классом. Параметр T в угловых скобках называется
универсальным параметром, так как вместо него можно подставить любой тип. При этом пока мы не знаем, какой именно это будет
тип: String, int или какой-то другой. Причем буква T выбрана условно, это может и любая другая буква или набор символов.
После объявления класса мы можем применить универсальный параметр T: так далее в классе объявляется переменная этого типа,
которой затем присваивается значение в конструкторе.
Метод getId() возвращает значение переменной id, но так как данная переменная представляет тип T, то данный метод также возвращает объект типа T: public T getId().
Используем данный класс:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 | public class Program{ public static void main(String[] args) { Account<String> acc1 = new Account<String>("2345", 5000); String acc1Id = acc1.getId(); System.out.println(acc1Id); Account<Integer> acc2 = new Account<Integer>(2345, 5000); Integer acc2Id = acc2.getId(); System.out.println(acc2Id); }}class Account<T>{ private T id; private int sum; Account(T id, int sum){ this.id = id; this.sum = sum; } public T getId() { return id; } public int getSum() { return sum; } public void setSum(int sum) { this.sum = sum; }} |
При определении переменной даннного класса и создании объекта после имени класса в угловых скобках нужно указать, какой именно тип будет использоваться
вместо универсального параметра. При этом надо учитывать, что они работают только с объектами, но не работают с примитивными типами.
То есть мы можем написать Account<Integer>, но не можем использовать тип int или double, например, Account<int>.
Вместо примитивных типов надо использовать классы-обертки: Integer вместо int, Double вместо double и т.д.
Например, первый объект будет использовать тип String, то есть вместо T будет подставляться String:
1 | Account<String> acc1 = new Account<String>("2345", 5000); |
В этом случае в качестве первого параметра в конструктор передается строка.
А второй объект использует тип int (Integer):
1 | Account<Integer> acc2 = new Account<Integer>(2345, 5000); |
Обобщенные интерфейсы
Интерфейсы, как и классы, также могут быть обобщенными. Создадим обобщенный интерфейс Accountable и используем его в программе:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 | public class Program{ public static void main(String[] args) { Accountable<String> acc1 = new Account("1235rwr", 5000); Account acc2 = new Account("2373", 4300); System.out.println(acc1.getId()); System.out.println(acc2.getId()); }}interface Accountable<T>{ T getId(); int getSum(); void setSum(int sum);}class Account implements Accountable<String>{ private String id; private int sum; Account(String id, int sum){ this.id = id; this.sum = sum; } public String getId() { return id; } public int getSum() { return sum; } public void setSum(int sum) { this.sum = sum; }} |
При реализации подобного интерфейса есть две стратегии. В данном случае реализована первая стратегия, когда при реализации для универсального параметра интерфейса задается конкретный тип, как например, в данном случае это тип String. Тогда класс, реализующий интерфейс, жестко привязан к этому типу.
Вторая стратегия представляет определение обобщенного класса, который также использует тот же универсальный параметр:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 | public class Program{ public static void main(String[] args) { Account<String> acc1 = new Account<String>("1235rwr", 5000); Account<String> acc2 = new Account<String>("2373", 4300); System.out.println(acc1.getId()); System.out.println(acc2.getId()); }}interface Accountable<T>{ T getId(); int getSum(); void setSum(int sum);}class Account<T> implements Accountable<T>{ private T id; private int sum; Account(T id, int sum){ this.id = id; this.sum = sum; } public T getId() { return id; } public int getSum() { return sum; } public void setSum(int sum) { this.sum = sum; }} |
Обобщенные методы
Кроме обобщенных типов можно также создавать обобщенные методы, которые точно также будут использовать универсальные параметры. Например:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 | public class Program{ public static void main(String[] args) { Printer printer = new Printer(); String[] people = {"Tom", "Alice", "Sam", "Kate", "Bob", "Helen"}; Integer[] numbers = {23, 4, 5, 2, 13, 456, 4}; printer.<String>print(people); printer.<Integer>print(numbers); }}class Printer{ public <T> void print(T[] items){ for(T item: items){ System.out.println(item); } }} |
Особенностью обобщенного метода является использование универсального параметра в объявлении метода после всех модификаторов и перед типом возвращаемого значения.
1 | public <T> void print(T[] items) |
Затем внутри метода все значения типа T будут представлять данный универсальный параметр.
При вызове подобного метода перед его именем в угловых скобках указывается, какой тип будет передаваться на место универсального параметра:
1 2 | printer.<String>print(people);printer.<Integer>print(numbers); |
Использование нескольких универсальных параметров
Мы можем также задать сразу несколько универсальных параметров:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 | public class Program{ public static void main(String[] args) { Account<String, Double> acc1 = new Account<String, Double>("354", 5000.87); String id = acc1.getId(); Double sum = acc1.getSum(); System.out.printf("Id: %s Sum: %f \n", id, sum); }}class Account<T, S>{ private T id; private S sum; Account(T id, S sum){ this.id = id; this.sum = sum; } public T getId() { return id; } public S getSum() { return sum; } public void setSum(S sum) { this.sum = sum; }} |
В данном случае тип String будет передаваться на место параметра T, а тип Double - на место параметра S.
Обобщенные конструкторы
Конструкторы как и методы также могут быть обобщенными. В этом случае перед конструктором также указываются в угловых скобках универсальные параметры:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 | public class Program{ public static void main(String[] args) { Account acc1 = new Account("cid2373", 5000); Account acc2 = new Account(53757, 4000); System.out.println(acc1.getId()); System.out.println(acc2.getId()); }}class Account{ private String id; private int sum; <T>Account(T id, int sum){ this.id = id.toString(); this.sum = sum; } public String getId() { return id; } public int getSum() { return sum; } public void setSum(int sum) { this.sum = sum; }} |
В данном случае конструктор принимает параметр id, который представляет тип T. В конструкторе его значение превращается в строку и сохраняется в локальную переменную.
Когда мы указываем универсальный параметр у обобщений, то по умолчанию он может представлять любой тип. Однако иногда необходимо, чтобы параметр соответствовал только некоторому ограниченному набору типов. В этом случае применяются ограничения, которые позволяют указать базовый класс, которому должен соответствовать параметр.
Для установки ограничения после универсального параметра ставится слово extends, после которого указывается базовый класс ограничения:
1 2 | class Account{ }class Transaction<T extends Account>{ } |
К примеру, в данном случае для параметра T в Transaction ограничением является класс Account. То есть на место параметра T мы можем передать либо класс Account, либо один из его классов-наследников.
Например, рассмотрим следующую программу:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 | public class Program{ public static void main(String[] args) { Account acc1 = new Account("1876", 4500); Account acc2 = new Account("3476", 1500); Transaction<Account> tran1 = new Transaction<Account>(acc1,acc2, 4000); tran1.execute(); tran1 = new Transaction<Account>(acc1,acc2, 4000); tran1.execute(); }}class Transaction<T extends Account>{ private T from; // с какого счета перевод private T to; // на какой счет перевод private int sum; // сумма перевода Transaction(T from, T to, int sum){ this.from = from; this.to = to; this.sum = sum; } public void execute(){ if (from.getSum() > sum) { from.setSum(from.getSum() - sum); to.setSum(to.getSum() + sum); System.out.printf("Account %s: %d \nAccount %s: %d \n", from.getId(), from.getSum(),to.getId(), to.getSum()); } else{ System.out.printf("Operation is invalid"); } }}class Account{ private String id; private int sum; Account(String id, int sum){ this.id = id; this.sum = sum; } public String getId() { return id; } public int getSum() { return sum; } public void setSum(int sum) { this.sum = sum; }} |
В данном случае класс Transaction, который представляет операцию перевода средств между двумя счетами, типизирован параметром T, у которого в качестве ограничения установлен класс Account. При создании объекта Transaction в его конструктор передаются два объекта Account - два счета, между которыми надо осуществить перевод, и сумма перевода.
При этом важно понимать, что поскольку мы установили подобное ограничение, то компилятор будет распознавать объекты типа T как объекты типа Account. И в этом случае мы можем вызывать у объектов типа T методы класса Account. И мы бы не смогли бы это сделать, если бы мы не задали подобного ограничения:
1 2 3 | class Transaction<T>{ // остальное содержимое} |
В этом случае была бы ошибка.
Обобщенные типы в качестве ограничений
В качестве ограничений могут выступать и другие обобщения, которые сами могут иметь ограничения:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 | public class Program{ public static void main(String[] args) { Account<String> acc1 = new Account<String>("1876", 4500); Account<String> acc2 = new Account<String>("3476", 1500); Transaction<Account<String>> tran1 = new Transaction<Account<String>>(acc1,acc2, 4000); tran1.execute(); tran1 = new Transaction<Account<String>>(acc1,acc2, 4000); tran1.execute(); }}class Transaction<T extends Account<String>>{ private T from; // с какого счета перевод private T to; // на какой счет перевод private int sum; // сумма перевода Transaction(T from, T to, int sum){ this.from = from; this.to = to; this.sum = sum; } public void execute(){ if (from.getSum() > sum) { from.setSum(from.getSum() - sum); to.setSum(to.getSum() + sum); System.out.printf("Account %s: %d \nAccount %s: %d \n", from.getId(), from.getSum(),to.getId(), to.getSum()); } else{ System.out.printf("Operation is invalid"); } }}class Account<T>{ private T id; private int sum; Account(T id, int sum){ this.id = id; this.sum = sum; } public T getId() { return id; } public int getSum() { return sum; } public void setSum(int sum) { this.sum = sum; }} |
В данном случае ограничением для Transaction является тип Account, который типизирован типом String.
Интерфейсы в качестве ограничений
В качестве ограничений могут выступать также интерфейсы. В этом случае передаваемый на место универсального параметра тип должен реализовать данный интерфейс:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 | public class Program{ public static void main(String[] args) { Account acc1 = new Account("1235rwr", 5000); Account acc2 = new Account("2373", 4300); Transaction<Account> tran1 = new Transaction<Account>(acc1, acc2, 1560); tran1.execute(); }}interface Accountable{ String getId(); int getSum(); void setSum(int sum);}class Account implements Accountable{ private String id; private int sum; Account(String id, int sum){ this.id = id; this.sum = sum; } public String getId() { return id; } public int getSum() { return sum; } public void setSum(int sum) { this.sum = sum; }}class Transaction<T extends Accountable>{ private T from; // с какого счета перевод private T to; // на какой счет перевод private int sum; // сумма перевода Transaction(T from, T to, int sum){ this.from = from; this.to = to; this.sum = sum; } public void execute(){ if (from.getSum() > sum) { from.setSum(from.getSum() - sum); to.setSum(to.getSum() + sum); System.out.printf("Account %s: %d \nAccount %s: %d \n", from.getId(), from.getSum(),to.getId(), to.getSum()); } else{ System.out.printf("Operation is invalid"); } }} |
Множественные ограничения
Также можно установить сразу несколько ограничений. Например, пусть класс Transaction может работать только с объектами, которые одновременно реализуют интерфейс Accountable и являются наследниками класса Person:
1 2 3 4 | class Person{}interface Accountable{}class Transaction<T extends Person & Accountable>{} |
Обобщенные классы могут участвовать в иерархии наследования: могут наследоваться от других, либо выполнять роль базовых классов. Рассмотрим различные ситуации.
Базовый обобщенный класс
При наследовании от обобщенного класса класс-наследник должен передавать данные о типе в конструкции базового класса:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | class Account<T>{ private T _id; T getId(){return _id;} Account(T id) { _id = id; }}class DepositAccount<T> extends Account<T>{ DepositAccount(T id){ super(id); }} |
В конструкторе DepositAccount идет обращение к конструктору базового класса, в который передаются данные о типе.
Варианты использования классов:
1 2 3 4 5 | DepositAccount dAccount1 = new DepositAccount(20);System.out.println(dAccount1.getId()); DepositAccount dAccount2 = new DepositAccount("12345");System.out.println(dAccount2.getId()); |
При этом класс-наследник может добавлять и использовать какие-то свои параметры типов:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 | class Account<T>{ private T _id; T getId(){return _id;} Account(T id) { _id = id; }}class DepositAccount<T, S> extends Account<T>{ private S _name; S getName(){return _name;} DepositAccount(T id, S name){ super(id); this._name=name; }} |
Варианты использования:
1 2 3 4 5 | DepositAccount<Integer, String> dAccount1 = new DepositAccount(20, "Tom");System.out.println(dAccount1.getId() + " : " + dAccount1.getName()); DepositAccount<String, Integer> dAccount2 = new DepositAccount("12345", 23456);System.out.println(dAccount2.getId() + " : " + dAccount2.getName()); |
И еще одна ситуация - класс-наследник вообще может не быть обобщенным:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | class Account<T>{ private T _id; T getId(){return _id;} Account(T id) { _id = id; }}class DepositAccount extends Account<Integer>{ DepositAccount(){ super(5); }} |
Здесь при наследовании явным образом указывается тип, который будет использоваться конструкциями базового класса, то есть тип Integer.
Затем в конструктор базового класса передается значение именно этого типа - в данном случае число 5.
Вариант использования:
1 2 | DepositAccount dAccount1 = new DepositAccount();System.out.println(dAccount1.getId()); |
Обобщенный класс-наследник
Также может быть ситуация, когда базовый класс является обычным необобщенным классом. Например:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 | class Account{ private String _name; String getName(){return _name;} Account(String name) { _name=name; }}class DepositAccount<T> extends Account{ private T _id; T getId(){return _id;} DepositAccount(String name, T id){ super(name); _id = id; }} |
В этом случае использование конструкций базового класса в наследнике происходит как обычно.
Преобразование обобщенных типов
Объект одного обобщенного типа можно привести к другому типу, если они используют один и тот же тип. Рассмотрим преобразование типов на примере следующих двух обобщенных классов:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | class Account<T>{ private T _id; T getId(){return _id;} Account(T id) { _id = id; }}class DepositAccount<T> extends Account<T>{ DepositAccount(T id){ super(id); }} |
Мы можем привести объект DepositAccount<Integer> к Account<Integer> или DepositAccount<String> к Account<String>:
1 2 3 | DepositAccount<Integer> depAccount = new DepositAccount(10);Account<Integer> account = (Account<Integer>)depAccount;System.out.println(account.getId()); |
Но сделать то же самое с разнотипными объектами мы не можем. Например, следующий код не будет работать:
1 2 | DepositAccount<Integer> depAccount = new DepositAccount(10);Account<String> account = (Account<String>)depAccount; |
При работе с объектами классов надо учитывать, что они все представляют ссылочные типы, то есть указывают на какой-то объект, расположенный в памяти. Чтобы понять возможные трудности, с которыми мы можем столкнуться, рассмотрим пример:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 | public class Program{ public static void main(String[] args) { Person tom = new Person("Tom", 23); tom.display(); // Person Tom Person bob = tom; bob.setName("Bob"); tom.display(); // Person Bob }}class Person{ private String name; private int age; Person(String name, int age){ this.name=name; this.age=age; } void setName(String name){ this.name = name; } void setAge(int age){ this.age = age; } void display(){ System.out.printf("Person Name: %s \n", name); }} |
Здесь создаем два объекта Person и один присваиваем другому. Но, несмотря на то, что мы изменяем только объект bob, вместе с ним изменяется и объект tom. Потому что после присвоения они указывают на одну и ту же область в памяти, где собственно данные об объекте Person и его полях и хранятся.
Чтобы избежать этой проблемы, необходимо создать отдельный объект для переменной bob, например, с помощью метода clone:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 | class Person implements Cloneable{ private String name; private int age; Person(String name, int age){ this.name=name; this.age=age; } void setName(String name){ this.name = name; } void setAge(int age){ this.age = age; } void display(){ System.out.printf("Person %s \n", name); } public Person clone() throws CloneNotSupportedException{ return (Person) super.clone(); }} |
Для реализации клонирования класс Person должен применить интерфейс Cloneable, который определяет метод clone.
Реализация этого метода просто возвращает вызов метода clone для родительского класса - то есть класса Object с преобразованием к типу Person.
Кроме того, на случай если класс не поддерживает клонирование, метод должен выбрасывать исключение CloneNotSupportedException, что определяется с помощью оператора throws.
Затем с помощью вызова этого метода мы можем осуществить копирование:
1 2 3 4 5 6 7 8 9 10 | try{ Person tom = new Person("Tom", 23); Person bob = tom.clone(); bob.setName("Bob"); tom.display(); // Person Tom}catch(CloneNotSupportedException ex){ System.out.println("Clonable not implemented");} |
Однако данный способ осуществляет неполное копирование и подойдет, если клонируемый объект не содержит сложных объектов. Например, пусть класс Book имеет следующее определение:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 | class Book implements Cloneable{ private String name; private Author author; public void setName(String n){ name=n;} public String getName(){ return name;} public void setAuthor(String n){ author.setName(n);} public String getAuthor(){ return author.getName();} Book(String name, String author){ this.name = name; this.author = new Author(author); } public String toString(){ return "Книга '" + name + "' (автор " + author + ")"; } public Book clone() throws CloneNotSupportedException{ return (Book) super.clone(); }}class Author{ private String name; public void setName(String n){ name=n;} public String getName(){ return name;} public Author(String name){ this.name=name; }} |
Если мы попробуем изменить автора книги, нас постигнет неудача:
1 2 3 4 5 6 7 8 9 10 | try{ Book book = new Book("War and Peace", "Leo Tolstoy"); Book book2 = book.clone(); book2.setAuthor("Ivan Turgenev"); System.out.println(book.getAuthor());}catch(CloneNotSupportedException ex){ System.out.println("Cloneable not implemented");} |
В этом случае, хотя переменные book и book2 будут указывать на разные объекты в памяти, но эти объекты при этом будут указывать на один объект Author.
И в этом случае нам необходимо выполнить полное копирование. Для этого надо определить метод клонирования у класса Author:
1 2 3 4 5 6 7 8 9 | class Author implements Cloneable{ // остальной код класса public Author clone() throws CloneNotSupportedException{ return (Author) super.clone(); }} |
И затем исправим метод clone в классе Book следующим образом:
1 2 3 4 5 6 | public Book clone() throws CloneNotSupportedException{ Book newBook = (Book) super.clone(); newBook.author=(Author) author.clone(); return newBook;} |
Начиная с версии Java 16 в язык была добавлена новая функциональность - Records (на русском нередко называют "записями"). Records представляют классы, которые предназначены для создания контейнеров неизменяемых данных. Кроме того, records позволяют упростить разработку, сократив объем кода.
Для определения классов record применяется ключевое слово record, после которого идет название и далее в круглых скобках список полей record:
1 2 3 | record название (поле1, поле2,...полеN){ // тело record} |
Рассмотрим следующий пример
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 | import java.util.Objects;public class Program{ public static void main (String args[]){ Person tom = new Person("Tom", 36); System.out.println(tom.toString()); }}class Person { private final String name; private final int age; Person(String name, int age) { this.name = name; this.age = age; } String name() { return name; } int age() { return age; } public boolean equals(Object o) { if (!(o instanceof Person)) return false; Person other = (Person) o; return other.name == name && other.age == age; } public int hashCode() { return Objects.hash(name, age); } public String toString() { return String.format("Person[name=%s, age=%d]", name, age); }} |
Здесь определен класс Person, который определяет две константы - name и age:
1 2 | private final String name;private final int age; |
Их значения устанавливаются в конструкторе. Больше никак их установить мы не можем. Таким образом, после создания объекта Person они будут хранить неизменяемые данные.
Для получения значений name и age предусмотрены одноименные методы:
1 2 | String name() { return name; }int age() { return age; } |
Кроме того, здесь переопределены унаследованные от класса Object методы equals(), hashCode() и toString().
В методе main создаем один объект класса Person и выводит на консоль его текстовое представление:
1 2 | Person tom = new Person("Tom", 36); System.out.println(tom.toString()); |
В итоге консоль нам выведет:
Person[name=Tom, age=36]
Теперь посмотрим, что нам предлагают Records - определим record, которая будет полностью аналогична вышеопределенному классу:
1 2 3 4 5 6 7 8 9 | public class Program{ public static void main (String args[]){ Person tom = new Person("Tom", 36); System.out.println(tom.toString()); }}record Person(String name, int age) { } |
Records определяются с помощью ключевого слова record, за которым следует название записи. Дальше идет список полей записи. То есть в данном случае определяется два поля - name и age. Причем по умолчанию все они будут приватными и иметь модификатор final.
Также будет создаваться конструктор с двумя параметрами name и age. А каждого поля автоматически будет создаваться одноименный общедоступный метод для получения значения это поля. Например, для поля name создается
метод name(), который возвращает значение поля name.
И также автоматически будут создаваться методы equals, hashCode и toString. Вообщем, данная record будет полностью аналогична вышеопределенному классу, но при этом содержит гораздо меньше
кода.
При необходимости мы можем вызывать все имеющиеся методы:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | public class Program{ public static void main (String args[]){ Person tom = new Person("Tom", 36); System.out.println(tom.name()); // Tom System.out.println(tom.age()); // 36 System.out.println(tom.hashCode()); Person bob = new Person("Bob", 21); Person tomas = new Person("Tom", 36); System.out.println(tom.equals(bob)); // false System.out.println(tom.equals(tomas)); // true }}record Person(String name, int age){ } |
Конструктор record
В примере выше применялась форма record:
1 | record Person(String name, int age) { } |
которая фактически создавала конструктор:
1 2 3 4 | Person(String name, int age) { this.name = name; this.age = age;} |
Этот конструктор называется каноническим. Он принимает параметры, которые называются также как и поля record, и передает полям значения соответствующих параметров.
Тем не менее при необходимости мы можем изменить логику конструктора. Так, мы можем переопределить логику конструктора. Например, что если при создании объекта будет передан невалидный возраст? Предусмотрим эту ситуацию, переопределив логику конструктора:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | public class Program{ public static void main (String args[]){ Person tom = new Person("Tom", -116); System.out.println(tom.toString()); }}record Person(String name, int age) { Person{ if(age<1 || age > 110){ age = 18; } }} |
В данном случае если передано невалидное значение, то применяем некоторое значение по умолчанию (число 18). В итоге фактически мы получим конструктор со следующим действием:
1 2 3 4 5 6 7 | Person(String name, int age) { if(age<1 || age > 110){ age = 18; } this.name = name; this.age = age;} |
В итоге программа выведет на консоль следующее:
Person[name=Tom, age=18]
Мы можем полностью переопределить канонический конструктор:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 | public class Program{ public static void main (String args[]){ Person tom = new Person("Tom", 36); System.out.println(tom.toString()); System.out.println(tom.name()); }}record Person(String name, int age) { Person(String name, int age){ if(age < 0 || age > 120) age = 18; this.name = name; this.age = age; }} |
Также мы можем определять какие-то другие конструкторы, но все они должны вызывать канонический конструктор:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | public class Program{ public static void main (String args[]){ Person tom = new Person("Tom", "Smith", 36); System.out.println(tom.toString()); }}record Person(String name, int age) { Person(String firstName, String lastName, int age){ this(firstName + " " + lastName, age); }} |
Здесь определен конструктор, который условно принимает имя, фамилию и возраст пользователя. Этот конструктор вызывает канонический конструктор,
передая ему значения для полей name и age: this(firstName + " " + lastName, age).
Консольный вывод программы:
Person[name=Tom Smith, age=36]
Переопределение методов
Также мы можем переопределить методы, которые имеет record по умолчанию. А это методы equals(), hashCode() и
toString() и методы, которые называются также, как и поля записи, и которые возвращают значения соответствующих полей.
Например, перепопределим для записи Person методы toString() и name():
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | public class Program{ public static void main (String args[]){ Person tom = new Person("Tom", 36); System.out.println(tom.toString()); System.out.println(tom.name()); }}record Person(String name, int age) { public String name() { return "Mister " + name; } public String toString() { return String.format("Person %s, Age: %d", name, age); }} |
Консольный вывод программ:
Person Tom, Age: 36 Mister Tom
Ограничения records
Следует учитывать, что мы не можем наследовать запись record от других классов. Также нельзя наследовать классы от records. Однако классы record могут реализовать интерфейсы. Кроме того, классы record не могут быть абстрактными.
В record нельзя явным образом определять нестатические поля и инициализаторы. Но можно определять статические переменные и инициализаторы, также как статические и нестатические методы:
1 2 3 4 5 6 7 8 | record Person(String name, int age){ static int minAge; static{ minAge = 18; System.out.println("Static initializer"); }} |
Классы. Объектно-ориентированное программирование
1. КЛАССЫ И ОБЪЕКТЫ
Базовые задачи:
Создание класса: Создайте класс
Carс полямиmake,modelиyear. Создайте объект этого класса.- Решение:java
class Car { String make; String model; int year; Car(String make, String model, int year) { this.make = make; this.model = model; this.year = year; } } public class Main { public static void main(String[] args) { Car myCar = new Car("Toyota", "Corolla", 2020); } }
- Решение:
Методы класса: Добавьте метод
displayInfo()в классCar, который выводит информацию о машине.- Решение:java
class Car { // поля... void displayInfo() { System.out.println(year + " " + make + " " + model); } }
- Решение:
Конструкторы: Создайте конструктор по умолчанию для класса
Car.- Решение:java
class Car { String make; String model; int year; Car() { this.make = "Unknown"; this.model = "Unknown"; this.year = 2000; } }
- Решение:
Создание нескольких объектов: Создайте массив объектов
Carи инициализируйте его.- Решение:java
Car[] cars = new Car[3]; cars[0] = new Car("Ford", "Focus", 2018); cars[1] = new Car("Honda", "Civic", 2019); cars[2] = new Car("Tesla", "Model S", 2021);
- Решение:
Общие методы: Напишите метод, который принимает объект
Carи выводит его информацию.- Решение:java
void printCarInfo(Car car) { car.displayInfo(); }
- Решение:
Сложные задачи:
Класс с объектами: Создайте класс
Library, который содержит объектыBook.- Решение:java
class Book { String title; String author; Book(String title, String author) { this.title = title; this.author = author; } } class Library { Book[] books; Library(Book[] books) { this.books = books; } }
- Решение:
Методы для манипуляции с объектами: Добавьте метод для добавления книги в библиотеку.
- Решение:java
void addBook(Book book) { // реализация добавления книги }
- Решение:
Сравнение объектов: Реализуйте метод
equals()для классаCar.- Решение:java
@Override public boolean equals(Object obj) { if (this == obj) return true; if (!(obj instanceof Car)) return false; Car other = (Car) obj; return this.make.equals(other.make) && this.model.equals(other.model); }
- Решение:
Класс с приватными полями: Создайте класс с приватными полями и методами доступа.
- Решение:java
class Person { private String name; private int age; public String getName() { return name; } public void setName(String name) { this.name = name; } }
- Решение:
Статические методы: Создайте статический метод в классе
Car, который возвращает максимальную скорость.- Решение:java
static int maxSpeed() { return 200; // км/ч }
- Решение:
2. ПАКЕТЫ
Базовые задачи:
Создание пакета: Создайте пакет
com.exampleи классMainвнутри него.- Решение:java
package com.example; public class Main { public static void main(String[] args) { System.out.println("Hello from package com.example!"); } }
- Решение:
Импорт классов: Импортируйте класс
Scannerизjava.util.- Решение:java
import java.util.Scanner;
- Решение:
Использование пользовательского пакета: Создайте класс в другом файле и используйте его в главном классе.
- Решение:java
// File: com/example/Car.java package com.example; public class Car { // поля и методы... } // File: com/example/Main.java package com.example; public class Main { public static void main(String[] args) { Car myCar = new Car(); } }
- Решение:
Доступ к классам в разных пакетах: Создайте класс в одном пакете и используйте его в другом.
- Решение:java
// File: com/example/Car.java package com.example; public class Car { // поля и методы... } // File: com/example/utils/Utils.java package com.example.utils; import com.example.Car; public class Utils { public void useCar() { Car car = new Car(); } }
- Решение:
Пакетная структура: Создайте вложенные пакеты, такие как
com.example.modelsиcom.example.services.- Решение:java
package com.example.models; public class Car { // поля и методы... } package com.example.services; import com.example.models.Car; public class CarService { // методы для работы с Car }
- Решение:
Сложные задачи:
Создание иерархии пакетов: Создайте несколько классов в разных пакетах и используйте их друг с другом.
- Решение:java
package com.example.models; public class Car { /* поля и методы... */ } package com.example.services; import com.example.models.Car; public class CarService { /* методы для работы с Car */ }
- Решение:
Классы в одном пакете: Создайте несколько классов в одном пакете и продемонстрируйте взаимодействие между ними.
- Решение:java
package com.example; public class Car { /* поля и методы... */ } public class Main { public static void main(String[] args) { Car car = new Car(); } }
- Решение:
Использование пакетов в библиотеке: Импортируйте стандартные библиотеки в проект и используйте их.
- Решение:java
import java.util.List; public class Example { List<String> names; }
- Решение:
Создание библиотеки: Создайте пакет, который будет использоваться как библиотека, и импортируйте его в другом проекте.
- Решение:java
// Пакет com.mylibrary package com.mylibrary; public class MyLibraryClass { /* методы... */ } // Использование в другом проекте import com.mylibrary.MyLibraryClass;
- Решение:
Доступ к классам с различными модификаторами доступа: Создайте классы с различными модификаторами доступа и попробуйте получить доступ к их полям из другого пакета.
- Решение:java
// com.example.models.Person.java package com.example.models; public class Person { public String name; protected int age; private String ssn; } // com.example.Main.java package com.example; import com.example.models.Person; public class Main { public static void main(String[] args) { Person person = new Person(); System.out.println(person.name); // доступно } }
- Решение:
3. МОДИФИКАТОРЫ ДОСТУПА И ИНКАПСУЛЯЦИЯ
Базовые задачи:
Создание класса с инкапсуляцией: Создайте класс
BankAccountс полямиbalance,accountNumber. Инкапсулируйте их.- Решение:java
class BankAccount { private double balance; private String accountNumber; public double getBalance() { return balance; } public void deposit(double amount) { balance += amount; } }
- Решение:
Доступ к приватным полям: Создайте методы доступа для приватных полей.
- Решение:java
public String getAccountNumber() { return accountNumber; }
- Решение:
Использование protected: Создайте класс
SavingsAccount, который наследуетBankAccountи добавьте полеinterestRate.- Решение:java
class SavingsAccount extends BankAccount { private double interestRate; }
- Решение:
Доступ к защищенным полям: В классе
SavingsAccountсоздайте метод для полученияinterestRate.- Решение:java
public double getInterestRate() { return interestRate; }
- Решение:
Использование public: Создайте класс
User, который будет иметь публичные поля.- Решение:java
class User { public String username; public String password; }
- Решение:
Сложные задачи:
Полная инкапсуляция: Создайте класс
Employeeс полямиnameиsalary. Инкапсулируйте их и добавьте методы для управления ими.- Решение:java
class Employee { private String name; private double salary; public void setName(String name) { this.name = name; } public String getName() { return name; } }
- Решение:
Различные уровни доступа: Создайте несколько классов и продемонстрируйте доступ к полям с различными уровнями доступа.
- Решение:java
class A { public int publicField; protected int protectedField; private int privateField; } class B extends A { void method() { System.out.println(publicField); System.out.println(protectedField); // System.out.println(privateField); // недоступно } }
- Решение:
Проверка доступа через методы: Создайте метод, который проверяет доступ к защищенным и приватным полям.
- Решение:java
class C { private int secret; public void revealSecret() { System.out.println(secret); } }
- Решение:
Динамическое создание объектов: Создайте класс, который создает объекты другого класса через публичные методы.
- Решение:java
class Factory { public Car createCar(String make, String model) { return new Car(make, model); } }
- Решение:
Инкапсуляция в контексте проекта: Создайте структуру классов, которая демонстрирует инкапсуляцию в реальном проекте (например, банковская система).
- Решение:java
class Bank { private List<BankAccount> accounts; public void addAccount(BankAccount account) { accounts.add(account); } }
- Решение:
4. СТАТИЧЕСКИЕ ЧЛЕНЫ И МОДИФИКАТОР STATIC
Базовые задачи:
Создание статического поля: Создайте класс
Counterс статическим полем для отслеживания количества созданных объектов.- Решение:java
class Counter { private static int count = 0; public Counter() { count++; } public static int getCount() { return count; } }
- Решение:
Статический метод: Добавьте статический метод, который возвращает количество объектов
Counter.- Решение:java
public static int getCount() { return count; }
- Решение:
Создание статического блока: Создайте статический блок, который инициализирует статические поля.
- Решение:java
static { count = 0; }
- Решение:
Статические методы в других классах: Создайте класс
MathUtilsс статическими методами для выполнения математических операций.- Решение:java
class MathUtils { public static int add(int a, int b) { return a + b; } }
- Решение:
Статические импортированные методы: Импортируйте статический метод
Math.max()и используйте его.- Решение:java
import static java.lang.Math.max; public class Example { public static void main(String[] args) { int result = max(5, 10); } }
- Решение:
Сложные задачи:
Статические переменные в контексте класса: Создайте класс
Student, где статическое поле хранит общее количество студентов.- Решение:java
class Student { private static int totalStudents = 0; public Student() { totalStudents++; } public static int getTotalStudents() { return totalStudents; } }
- Решение:
Статические методы и вызовы: Создайте класс, который имеет статический метод для вычисления факториала.
- Решение:java
class MathUtils { public static int factorial(int n) { if (n == 0) return 1; return n * factorial(n - 1); } }
- Решение:
Статические и нестатические методы: Создайте класс с статическими и нестатическими методами и проиллюстрируйте их использование.
- Решение:java
class Example { public static void staticMethod() { /* реализация */ } public void instanceMethod() { /* реализация */ } }
- Решение:
Статические вложенные классы: Создайте статический вложенный класс внутри другого класса.
- Решение:java
class Outer { static class Inner { void display() { System.out.println("Inner class"); } } }
- Решение:
Статические методы в интерфейсе: Создайте интерфейс с статическими методами и реализуйте его.
- Решение:java
interface MathOperations { static int square(int x) { return x * x; } }
- Решение:
5. ОБЪЕКТЫ КАК ПАРАМЕТРЫ МЕТОДОВ
Базовые задачи:
Передача объекта в метод: Создайте метод, который принимает объект
Carв качестве параметра.- Решение:java
class Car { String make; public Car(String make) { this.make = make; } } class Test { void displayCar(Car car) { System.out.println(car.make); } }
- Решение:
Изменение состояния объекта: Напишите метод, который изменяет свойства объекта
Car.- Решение:java
void updateCar(Car car, String newMake) { car.make = newMake; }
- Решение:
Создание метода с несколькими параметрами: Создайте метод, который принимает два объекта
Car.- Решение:java
void compareCars(Car car1, Car car2) { // реализация }
- Решение:
Использование возвращаемых значений: Создайте метод, который возвращает объект
Car.- Решение:java
Car createCar(String make) { return new Car(make); }
- Решение:
Передача массива объектов: Напишите метод, который принимает массив объектов
Car.- Решение:java
void displayCars(Car[] cars) { for (Car car : cars) { System.out.println(car.make); } }
- Решение:
Сложные задачи:
Метод с объектами и возвращаемыми значениями: Создайте метод, который принимает два объекта
Car, сравнивает их и возвращает один из них.- Решение:java
Car compareCars(Car car1, Car car2) { return car1.make.equals(car2.make) ? car1 : car2; }
- Решение:
Метод, принимающий список объектов: Создайте метод, который принимает
List<Car>и выводит информацию о всех автомобилях.- Решение:java
void displayCarList(List<Car> carList) { for (Car car : carList) { System.out.println(car.make); } }
- Решение:
Изменение списка объектов: Создайте метод, который принимает список объектов и изменяет их.
- Решение:java
void updateCarList(List<Car> cars, String newMake) { for (Car car : cars) { car.make = newMake; } }
- Решение:
Сравнение объектов в методе: Напишите метод, который сравнивает два объекта
Carи возвращает результат сравнения.- Решение:java
boolean isSameCar(Car car1, Car car2) { return car1.make.equals(car2.make); }
- Решение:
Метод с объектами и массивами: Напишите метод, который принимает массив объектов
Carи возвращает массив их марок.- Решение:java
String[] getCarMakes(Car[] cars) { String[] makes = new String[cars.length]; for (int i = 0; i < cars.length; i++) { makes[i] = cars[i].make; } return makes; }
- Решение:
6. ВНУТРЕННИЕ И ВЛОЖЕННЫЕ КЛАССЫ
Базовые задачи:
Создание вложенного класса: Создайте класс
Outerс вложенным классомInner.- Решение:java
class Outer { class Inner { void display() { System.out.println("Inner class"); } } }
- Решение:
Доступ к полям внешнего класса: Внутренний класс должен иметь доступ к полям внешнего класса.
- Решение:java
class Outer { private String outerField = "Outer field"; class Inner { void display() { System.out.println(outerField); } } }
- Решение:
Создание экземпляра внутреннего класса: Создайте метод в классе
Outer, который возвращает экземплярInner.- Решение:java
class Outer { class Inner { /* реализация */ } Inner createInner() { return new Inner(); } }
- Решение:
Вложенные классы и методы: Создайте вложенный класс внутри метода.
- Решение:java
class Outer { void createInner() { class Inner { void display() { System.out.println("Inner class"); } } Inner inner = new Inner(); inner.display(); } }
- Решение:
Статический вложенный класс: Создайте статический вложенный класс и используйте его.
- Решение:java
class Outer { static class StaticInner { void display() { System.out.println("Static Inner class"); } } }
- Решение:
Сложные задачи:
Вложенные классы с параметрами: Создайте внутренний класс, который принимает параметры в конструкторе.
- Решение:java
class Outer { class Inner { private String name; Inner(String name) { this.name = name; } } }
- Решение:
Использование статических вложенных классов: Создайте статический вложенный класс, который использует статическое поле внешнего класса.
- Решение:java
class Outer { static String outerField = "Outer field"; static class StaticInner { void display() { System.out.println(outerField); } } }
- Решение:
Вложенные классы с методами: Создайте вложенный класс с методами для взаимодействия с внешним классом.
- Решение:java
class Outer { private String outerField = "Outer field"; class Inner { void show() { System.out.println(outerField); } } }
- Решение:
Внутренние классы как параметры методов: Создайте метод, который принимает внутренний класс в качестве параметра.
- Решение:java
class Outer { class Inner { void display() { /* реализация */ } } void acceptInner(Inner inner) { inner.display(); } }
- Решение:
Анонимные внутренние классы: Создайте анонимный внутренний класс и используйте его.
- Решение:java
class Outer { void createAnonymous() { Inner inner = new Inner() { void display() { System.out.println("Anonymous Inner class"); } }; inner.display(); } class Inner { void display() { /* реализация */ } } }
- Решение:
7. НАСЛЕДОВАНИЕ
Базовые задачи:
Создание базового и производного классов: Создайте класс
Animalи классDog, который наследуетAnimal.- Решение:java
class Animal { void sound() { System.out.println("Animal sound"); } } class Dog extends Animal { void sound() { System.out.println("Bark"); } }
- Решение:
Использование методов базового класса: Создайте метод в производном классе, который вызывает метод базового класса.
- Решение:java
class Dog extends Animal { void sound() { super.sound(); // вызывает метод sound() из Animal System.out.println("Bark"); } }
- Решение:
Создание конструктора производного класса: Реализуйте конструктор в классе
Dog, который вызывает конструктор классаAnimal.- Решение:java
class Animal { Animal() { System.out.println("Animal created"); } } class Dog extends Animal { Dog() { super(); // вызывает конструктор Animal System.out.println("Dog created"); } }
- Решение:
Полиморфизм через наследование: Создайте массив
Animal, в который добавьте объектыDogиCat, и вызовите их методы.- Решение:java
Animal[] animals = { new Dog(), new Cat() }; for (Animal animal : animals) { animal.sound(); }
- Решение:
Переопределение методов: Реализуйте метод, который переопределяет метод базового класса.
- Решение:java
class Cat extends Animal { void sound() { System.out.println("Meow"); } }
- Решение:
Сложные задачи:
Многоуровневое наследование: Создайте иерархию классов, состоящую из нескольких уровней.
- Решение:java
class Animal { /* ... */ } class Mammal extends Animal { /* ... */ } class Dog extends Mammal { /* ... */ }
- Решение:
Использование абстрактных классов в наследовании: Создайте абстрактный класс
Shapeи его производные классыCircleиRectangle.- Решение:java
abstract class Shape { abstract void draw(); } class Circle extends Shape { void draw() { System.out.println("Drawing Circle"); } } class Rectangle extends Shape { void draw() { System.out.println("Drawing Rectangle"); } }
- Решение:
Реализация интерфейсов через наследование: Создайте интерфейс
Flyableи классы, которые его реализуют.- Решение:java
interface Flyable { void fly(); } class Bird implements Flyable { public void fly() { System.out.println("Bird is flying"); } }
- Решение:
Вызов методов в наследовании: Создайте класс, который вызывает методы базового класса из производного класса.
- Решение:java
class A { void display() { System.out.println("Class A"); } } class B extends A { void show() { display(); // вызов метода A } }
- Решение:
Применение final в наследовании: Используйте модификатор
finalдля предотвращения переопределения метода в производном классе.- Решение:java
class A { final void display() { System.out.println("Final method in A"); } } class B extends A { // void display() { } // ошибка, не может переопределить final метод }
- Решение:
8. АБСТРАКТНЫЕ КЛАССЫ
Базовые задачи:
Создание абстрактного класса: Создайте абстрактный класс
Animalс абстрактным методомsound().- Решение:java
abstract class Animal { abstract void sound(); }
- Решение:
Реализация абстрактного класса: Создайте класс
Dog, который наследуетAnimalи реализует методsound().- Решение:java
class Dog extends Animal { void sound() { System.out.println("Bark"); } }
- Решение:
Создание метода в абстрактном классе: Добавьте обычный метод в абстрактный класс.
- Решение:java
abstract class Animal { void eat() { System.out.println("Eating..."); } abstract void sound(); }
- Решение:
Создание массива абстрактных классов: Создайте массив объектов
Animalи инициализируйте его экземплярамиDog.- Решение:java
Animal[] animals = { new Dog(), new Cat() };
- Решение:
Использование абстрактных классов в методах: Создайте метод, который принимает абстрактный класс в качестве параметра.
- Решение:java
void makeSound(Animal animal) { animal.sound(); }
- Решение:
Сложные задачи:
Несколько абстрактных методов: Создайте абстрактный класс с несколькими абстрактными методами и реализуйте их в производных классах.
- Решение:java
abstract class Shape { abstract void draw(); abstract double area(); } class Circle extends Shape { void draw() { /* реализация */ } double area() { return Math.PI * radius * radius; } }
- Решение:
Наследование абстрактных классов: Создайте иерархию классов с несколькими уровнями наследования от абстрактного класса.
- Решение:java
abstract class Animal { /* ... */ } class Mammal extends Animal { /* ... */ } class Dog extends Mammal { /* ... */ }
- Решение:
Абстрактные классы и интерфейсы: Создайте абстрактный класс, который реализует интерфейс.
- Решение:java
interface Movable { void move(); } abstract class Vehicle implements Movable { // реализация интерфейса }
- Решение:
Применение final с абстрактными классами: Используйте модификатор
finalв абстрактном классе для предотвращения его наследования.- Решение:java
final abstract class Base { /* ... */ } // ошибка, final не может быть использован с абстрактным классом
- Решение:
Класс с абстрактными методами и обычными: Создайте абстрактный класс с обычными методами и абстрактными методами.
- Решение:java
abstract class AbstractClass { void concreteMethod() { /* реализация */ } abstract void abstractMethod(); }
- Решение:
9. ИНТЕРФЕЙСЫ
Базовые задачи:
Создание интерфейса: Создайте интерфейс
Animalс методомsound().- Решение:java
interface Animal { void sound(); }
- Решение:
Реализация интерфейса: Создайте класс
Dog, который реализует интерфейсAnimal.- Решение:java
class Dog implements Animal { public void sound() { System.out.println("Bark"); } }
- Решение:
Создание нескольких классов, реализующих интерфейс: Создайте классы
CatиBird, которые также реализуют интерфейсAnimal.- Решение:java
class Cat implements Animal { public void sound() { System.out.println("Meow"); } } class Bird implements Animal { public void sound() { System.out.println("Tweet"); } }
- Решение:
Создание метода, принимающего интерфейс: Создайте метод, который принимает объект
Animalи вызывает его методsound().- Решение:java
void makeSound(Animal animal) { animal.sound(); }
- Решение:
Использование интерфейса в массиве: Создайте массив объектов
Animalи заполните его экземплярамиDog,CatиBird.- Решение:java
Animal[] animals = { new Dog(), new Cat(), new Bird() };
- Решение:
Сложные задачи:
Несколько интерфейсов: Создайте два интерфейса и реализуйте их в одном классе.
- Решение:java
interface Flyable { void fly(); } interface Swimmable { void swim(); } class Duck implements Flyable, Swimmable { public void fly() { /* реализация */ } public void swim() { /* реализация */ } }
- Решение:
Использование интерфейсов в коллекциях: Создайте метод, который принимает список объектов, реализующих интерфейс
Animal.- Решение:java
void makeSounds(List<Animal> animals) { for (Animal animal : animals) { animal.sound(); } }
- Решение:
Статические методы в интерфейсах: Создайте интерфейс с статическим методом и используйте его.
- Решение:java
interface MathUtils { static int add(int a, int b) { return a + b; } }
- Решение:
Интерфейсы и наследование: Создайте интерфейс, который наследует другой интерфейс.
- Решение:java
interface Vehicle { void drive(); } interface ElectricVehicle extends Vehicle { void charge(); }
- Решение:
Использование интерфейсов с абстрактными классами: Создайте абстрактный класс, реализующий интерфейс.
- Решение:java
abstract class AbstractAnimal implements Animal { // реализация метода sound() }
- Решение:
10. ИСКЛЮЧЕНИЯ
Базовые задачи:
Создание исключения: Создайте собственное исключение
MyException.- Решение:java
class MyException extends Exception { public MyException(String message) { super(message); } }
- Решение:
Генерация исключения: Создайте метод, который выбрасывает ваше исключение.
- Решение:java
void throwMyException() throws MyException { throw new MyException("My custom exception occurred"); }
- Решение:
Обработка исключения: Напишите блок
try-catchдля обработки вашего исключения.- Решение:java
try { throwMyException(); } catch (MyException e) { System.out.println(e.getMessage()); }
- Решение:
Создание цепочки исключений: Создайте метод, который выбрасывает исключение, обернутое в другое.
- Решение:java
void method() throws MyException { throw new MyException("Chained exception"); } void anotherMethod() { try { method(); } catch (MyException e) { throw new RuntimeException(e); } }
- Решение:
Использование finally: Создайте блок
finallyдля выполнения кода независимо от обработки исключений.- Решение:java
try { // код, который может выбросить исключение } catch (Exception e) { // обработка исключения } finally { // этот блок всегда выполнится }
- Решение:
Сложные задачи:
Создание пользовательского исключения с дополнительными полями: Создайте исключение, которое хранит дополнительную информацию.
- Решение:java
class MyException extends Exception { private int errorCode; public MyException(String message, int errorCode) { super(message); this.errorCode = errorCode; } }
- Решение:
Обработка нескольких исключений: Обработайте несколько различных исключений в одном блоке
catch.- Решение:java
try { // код, который может выбросить несколько исключений } catch (IOException | SQLException e) { // обработка }
- Решение:
Создание иерархии исключений: Создайте базовый класс исключения и производные классы.
- Решение:java
class BaseException extends Exception { /* реализация */ } class DerivedException extends BaseException { /* реализация */ }
- Решение:
Логирование исключений: Создайте метод для логирования исключений.
- Решение:java
void logException(Exception e) { System.out.println("Exception: " + e.getMessage()); }
- Решение:
Использование try-with-resources: Используйте блок
try-with-resourcesдля автоматического закрытия ресурсов.- Решение:java
try (BufferedReader br = new BufferedReader(new FileReader("file.txt"))) { // чтение файла } catch (IOException e) { // обработка }
- Решение:
Для хранения наборов данных в Java предназначены массивы. Однако их не всегда удобно использовать, прежде всего потому, что они имеют фиксированную длину. Эту проблему в Java решают коллекции. Однако суть не только в гибких по размеру наборах объектов, но в и том, что классы коллекций реализуют различные алгоритмы и структуры данных, например, такие как стек, очередь, дерево и ряд других.
Классы коллекций располагаются в пакете java.util, поэтому перед применением коллекций следует подключить данный пакет.
Хотя в Java существует множество коллекций, но все они образуют стройную и логичную систему. Во-первых, в основе всех коллекций лежит применение того или иного интерфейса, который определяет базовый функционал. Среди этих интерфейсов можно выделить следующие:
Collection: базовый интерфейс для всех коллекций и других интерфейсов коллекций
Queue: наследует интерфейс Collection и представляет функционал для структур данных в виде очереди
Deque: наследует интерфейс Queue и представляет функционал для двунаправленных очередей
List: наследует интерфейс Collection и представляет функциональность простых списков
Set: также расширяет интерфейс Collection и используется для хранения множеств уникальных объектов
SortedSet: расширяет интерфейс Set для создания сортированных коллекций
NavigableSet: расширяет интерфейс SortedSet для создания коллекций, в которых можно осуществлять поиск по соответствию
Map: предназначен для созданий структур данных в виде словаря, где каждый элемент имеет определенный ключ и значение. В отличие от других интерфейсов коллекций не наследуется от интерфейса Collection
Эти интерфейсы частично реализуются абстрактными классами:
AbstractCollection: базовый абстрактный класс для других коллекций, который применяет интерфейс Collection
AbstractList: расширяет класс AbstractCollection и применяет интерфейс List, предназначен для создания коллекций в виде списков
AbstractSet: расширяет класс AbstractCollection и применяет интерфейс Set для создания коллекций в виде множеств
AbstractQueue: расширяет класс AbstractCollection и применяет интерфейс Queue, предназначен для создания коллекций в виде очередей и стеков
AbstractSequentialList: также расширяет класс AbstractList и реализует интерфейс List. Используется для создания связанных списков
AbstractMap: применяет интерфейс Map, предназначен для создания наборов по типу словаря с объектами в виде пары "ключ-значение"
С помощью применения вышеописанных интерфейсов и абстрактных классов в Java реализуется широкая палитра классов коллекций - списки, множества, очереди, отображения и другие, среди которых можно выделить следующие:
ArrayList: простой список объектов
LinkedList: представляет связанный список
ArrayDeque: класс двунаправленной очереди, в которой мы можем произвести вставку и удаление как в начале коллекции, так и в ее конце
HashSet: набор объектов или хеш-множество, где каждый элемент имеет ключ - уникальный хеш-код
TreeSet: набор отсортированных объектов в виде дерева
LinkedHashSet: связанное хеш-множество
PriorityQueue: очередь приоритетов
HashMap: структура данных в виде словаря, в котором каждый объект имеет уникальный ключ и некоторое значение
TreeMap: структура данных в виде дерева, где каждый элемент имеет уникальный ключ и некоторое значение
Схематично всю систему коллекций вкратце можно представить следующим образом:
Интерфейс Collection
Интерфейс Collection является базовым для всех коллекций, определяя основной функционал:
1 2 3 4 | public interface Collection<E> extends Iterable<E>{ // определения методов} |
Интерфейс Collection является обобщенным и расширяет интерфейс Iterable, поэтому все объекты коллекций можно перебирать в цикле по типу
for-each.
Среди методов интерфейса Collection можно выделить следующие:
boolean add (E item): добавляет в коллекцию объект item. При удачном добавлении возвращает true, при неудачном - falseboolean addAll (Collection<? extends E> col): добавляет в коллекцию все элементы из коллекции col. При удачном добавлении возвращает true, при неудачном - falsevoid clear (): удаляет все элементы из коллекцииboolean contains (Object item): возвращает true, если объект item содержится в коллекции, иначе возвращает falseboolean isEmpty (): возвращает true, если коллекция пуста, иначе возвращает falseIterator<E> iterator (): возвращает объект Iterator для обхода элементов коллекцииboolean remove (Object item): возвращает true, если объект item удачно удален из коллекции, иначе возвращается falseboolean removeAll (Collection<?> col): удаляет все объекты коллекции col из текущей коллекции. Если текущая коллекция изменилась, возвращает true, иначе возвращается falseboolean retainAll (Collection<?> col): удаляет все объекты из текущей коллекции, кроме тех, которые содержатся в коллекции col. Если текущая коллекция после удаления изменилась, возвращает true, иначе возвращается falseint size (): возвращает число элементов в коллекцииObject[] toArray (): возвращает массив, содержащий все элементы коллекции
Все эти и остальные методы, которые имеются в интерфейсе Collection, реализуются всеми коллекциями, поэтому в целом общие принципы работы с коллекциями
будут одни и те же. Единообразный интерфейс упрощает понимание и работу с различными типами коллекций. Так, добавление элемента будет производиться с помощью метода add, который принимает добавляемый элемент в качестве параметра.
Для удаления вызывается метод remove(). Метод clear будет очищать коллекцию, а метод size возвращать количество элементов в коллекции.
Для создания простых списков применяется интерфейс List, который расширяет функцональность интерфейса Collection. Некоторые наиболее часто используемые методы интерфейса List:
void add(int index, E obj): добавляет в список по индексу index объект obj
boolean addAll(int index, Collection<? extends E> col): добавляет в список по индексу index все элементы коллекции col. Если в результате добавления список был изменен, то возвращается true, иначе возвращается false
E get(int index): возвращает объект из списка по индексу index
int indexOf(Object obj): возвращает индекс первого вхождения объекта obj в список. Если объект не найден, то возвращается -1
int lastIndexOf(Object obj): возвращает индекс последнего вхождения объекта obj в список. Если объект не найден, то возвращается -1
ListIterator<E> listIterator (): возвращает объект ListIterator для обхода элементов списка
static <E> List<E> of(элементы): создает из набора элементов объект List
E remove(int index): удаляет объект из списка по индексу index, возвращая при этом удаленный объект
E set(int index, E obj): присваивает значение объекта obj элементу, который находится по индексу index
void sort(Comparator<? super E> comp): сортирует список с помощью компаратора comp
List<E> subList(int start, int end): получает набор элементов, которые находятся в списке между индексами start и end
По умолчанию в Java есть встроенная реализация этого интерфейса - класс ArrayList. Класс ArrayList представляет обобщенную коллекцию, которая наследует свою функциональность от класса AbstractList и применяет интерфейс List. Проще говоря, ArrayList представляет простой список, аналогичный массиву, за тем исключением, что количество элементов в нем не фиксировано.
ArrayList имеет следующие конструкторы:
ArrayList(): создает пустой списокArrayList(Collection <? extends E> col): создает список, в который добавляются все элементы коллекции col.ArrayList (int capacity): создает список, который имеет начальную емкость capacity
Емкость в ArrayList представляет размер массива, который будет использоваться для хранения объектов. При добавлении элементов фактически происходит перераспределение памяти - создание нового массива и копирование в него элементов из старого массива. Изначальное задание емкости ArrayList позволяет снизить подобные перераспределения памяти, тем самым повышая производительность.
Используем класс ArrayList и некоторые его методы в программе:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 | import java.util.ArrayList;public class Program{ public static void main(String[] args) { ArrayList<String> people = new ArrayList<String>(); // добавим в список ряд элементов people.add("Tom"); people.add("Alice"); people.add("Kate"); people.add("Sam"); people.add(1, "Bob"); // добавляем элемент по индексу 1 System.out.println(people.get(1));// получаем 2-й объект people.set(1, "Robert"); // установка нового значения для 2-го объекта System.out.printf("ArrayList has %d elements \n", people.size()); for(String person : people){ System.out.println(person); } // проверяем наличие элемента if(people.contains("Tom")){ System.out.println("ArrayList contains Tom"); } // удалим несколько объектов // удаление конкретного элемента people.remove("Robert"); // удаление по индексу people.remove(0); Object[] peopleArray = people.toArray(); for(Object person : peopleArray){ System.out.println(person); } }} |
Консольный вывод программы:
Bob ArrayList has 5 elements Tom Robert Alice Kate Sam ArrayList contains Tom Alice Kate Sam
Здесь объект ArrayList типизируется классом String, поэтому список будет хранить только строки. Поскольку класс ArrayList применяет интерфейс Collection<E>, то мы можем использовать методы данного интерфейса для управления объектами в списке.
Для добавления вызывается метод add.
С его помощью мы можем добавлять объект в конец списка: people.add("Tom"). Также мы можем добавить объект на определенное место в
списке, например, добавим объект на второе место (то есть по индексу 1, так как нумерация начинается с нуля): people.add(1, "Bob")
Метод size() позволяет узнать количество объектов в коллекции.
Проверку на наличие элемента в коллекции производится с помощью метода contains. А удаление с помощью метода remove.
И так же, как и с добавлением, мы можем удалить либо конкретный элемент people.remove("Tom");, либо элемент по индексу
people.remove(0); - удаление первого элемента.
Получить определенный элемент по индексу мы можем с помощью метода get(): String person = people.get(1);,
а установить элемент по индексу с помощью метода set: people.set(1, "Robert");
С помощью метода toArray() мы можем преобразовать список в массив объектов.
И поскольку класс ArrayList реализует интерфейс Iterable, то мы можем пробежаться по списку в цикле аля for-each: for(String person : people).
Хотя мы можем свободно добавлять в объект ArrayList дополнительные объекты, в отличие от массива, однако в реальности ArrayList использует для
хранения объектов опять же массив. По умолчанию данный массив предназначен для 10 объектов. Если в процессе программы добавляется гораздо больше, то
создается новый массив, который может вместить в себя все количество. Подобные перераспределения памяти уменьшают производительность. Поэтому
если мы точно знаем, что у нас список не будет содержать больше определенного количества элементов, например, 25, то мы можем сразу же явным образом
установить это количество, либо в конструкторе: ArrayList<String> people = new ArrayList<String>(25);,
либо с помощью метода ensureCapacity: people.ensureCapacity(25);
Очереди представляют структуру данных, работающую по принципу FIFO (first in - first out). То есть чем раньше был добавлен элемент в коллекцию, тем раньше он из нее удаляется. Это стандартная модель однонаправленной очереди. Однако бывают и двунаправленные - то есть такие, в которых мы можем добавить элемент не только в начала, но и в конец. И соответственно удалить элемент не только из конца, но и из начала.
Особенностью классов очередей является то, что они реализуют специальные интерфейсы Queue или Deque.
Интерфейс Queue
Обобщенный интерфейс Queue<E> расширяет базовый интерфейс Collection и определяет поведение класса в качестве однонаправленной
очереди. Свою функциональность он раскрывает через следующие методы:
E element(): возвращает, но не удаляет, элемент из начала очереди. Если очередь пуста, генерирует исключение
NoSuchElementExceptionboolean offer(E obj): добавляет элемент obj в конец очереди. Если элемент удачно добавлен, возвращает true, иначе - false
E peek(): возвращает без удаления элемент из начала очереди. Если очередь пуста, возвращает значение
nullE poll(): возвращает с удалением элемент из начала очереди. Если очередь пуста, возвращает значение
nullE remove(): возвращает с удалением элемент из начала очереди. Если очередь пуста, генерирует исключение
NoSuchElementException
Таким образом, у всех классов, которые реализуют данный интерфейс, будет метод offer для добавления в очередь, метод poll
для извлечения элемента из головы очереди, и методы peek и element, позволяющие просто получить элемент из головы очереди.
Интерфейс Deque
Интерфейс Deque расширяет вышеописанный интерфейс Queue и определяет поведение двунаправленной очереди, которая работает как обычная однонаправленная очередь, либо как стек, действующий по принципу LIFO (последний вошел - первый вышел).
Интерфейс Deque определяет следующие методы:
void addFirst(E obj): добавляет элемент в начало очереди
void addLast(E obj): добавляет элемент obj в конец очереди
E getFirst(): возвращает без удаления элемент из головы очереди. Если очередь пуста, генерирует исключение
NoSuchElementExceptionE getLast(): возвращает без удаления последний элемент очереди. Если очередь пуста, генерирует исключение
NoSuchElementExceptionboolean offerFirst(E obj): добавляет элемент obj в самое начало очереди. Если элемент удачно добавлен, возвращает true, иначе - false
boolean offerLast(E obj): добавляет элемент obj в конец очереди. Если элемент удачно добавлен, возвращает true, иначе - false
E peekFirst(): возвращает без удаления элемент из начала очереди. Если очередь пуста, возвращает значение
nullE peekLast(): возвращает без удаления последний элемент очереди. Если очередь пуста, возвращает значение
nullE pollFirst(): возвращает с удалением элемент из начала очереди. Если очередь пуста, возвращает значение
nullE pollLast(): возвращает с удалением последний элемент очереди. Если очередь пуста, возвращает значение
nullE pop(): возвращает с удалением элемент из начала очереди. Если очередь пуста, генерирует исключение
NoSuchElementExceptionvoid push(E element): добавляет элемент в самое начало очереди
E removeFirst(): возвращает с удалением элемент из начала очереди. Если очередь пуста, генерирует исключение
NoSuchElementExceptionE removeLast(): возвращает с удалением элемент из конца очереди. Если очередь пуста, генерирует исключение
NoSuchElementExceptionboolean removeFirstOccurrence(Object obj): удаляет первый встреченный элемент obj из очереди. Если удаление произшло, то возвращает true, иначе возвращает false.
boolean removeLastOccurrence(Object obj): удаляет последний встреченный элемент obj из очереди. Если удаление произшло, то возвращает true, иначе возвращает false.
Таким образом, наличие методов pop и push позволяет классам, реализующим этот элемент, действовать в качестве стека.
В тоже время имеющийся функционал также позволяет создавать двунаправленные очереди, что делает классы, применяющие данный интерфейс,
довольно гибкими.
Класс ArrayDeque
В Java очереди представлены рядом классов. Одни из низ - класс ArrayDeque<E>.
Этот класс представляют обобщенную двунаправленную очередь, наследуя функционал от класса AbstractCollection и применяя интерфейс
Deque.
В классе ArrayDeque определены следующие конструкторы:
ArrayDeque(): создает пустую очередьArrayDeque(Collection<? extends E> col): создает очередь, наполненную элементами из коллекции colArrayDeque(int capacity): создает очередь с начальной емкостью capacity. Если мы явно не указываем начальную емкость, то емкость по умолчанию будет равна 16
Пример использования класса:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 | import java.util.ArrayDeque;public class Program{ public static void main(String[] args) { ArrayDeque<String> states = new ArrayDeque<String>(); // стандартное добавление элементов states.add("Germany"); states.addFirst("France"); // добавляем элемент в самое начало states.push("Great Britain"); // добавляем элемент в самое начало states.addLast("Spain"); // добавляем элемент в конец коллекции states.add("Italy"); // получаем первый элемент без удаления String sFirst = states.getFirst(); System.out.println(sFirst); // Great Britain // получаем последний элемент без удаления String sLast = states.getLast(); System.out.println(sLast); // Italy System.out.printf("Queue size: %d \n", states.size()); // 5 // перебор коллекции while(states.peek()!=null){ // извлечение c начала System.out.println(states.pop()); } // очередь из объектов Person ArrayDeque<Person> people = new ArrayDeque<Person>(); people.addFirst(new Person("Tom")); people.addLast(new Person("Nick")); // перебор без извлечения for(Person p : people){ System.out.println(p.getName()); } }}class Person{ private String name; public Person(String value){ name=value; } String getName(){return name;}} |
Обобщенный класс LinkedList<E> представляет структуру данных в виде связанного списка. Он наследуется от класса AbstractSequentialList и реализует интерфейсы List, Dequeue и Queue.
То есть он соединяет функциональность работы со списком и фукциональность очереди.
Класс LinkedList имеет следующие конструкторы:
LinkedList(): создает пустой списокLinkedList(Collection<? extends E> col): создает список, в который добавляет все элементы коллекции col
LinkedList содержит все те методы, которые определены в интерфейсах List, Queue, Deque. Некоторые из них:
addFirst() / offerFirst(): добавляет элемент в начало списка
addLast() / offerLast(): добавляет элемент в конец списка
removeFirst() / pollFirst(): удаляет первый элемент из начала списка
removeLast() / pollLast(): удаляет последний элемент из конца списка
getFirst() / peekFirst(): получает первый элемент
getLast() / peekLast(): получает последний элемент
Рассмотрим применение связанного списка:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 | import java.util.LinkedList;public class Program{ public static void main(String[] args) { LinkedList<String> states = new LinkedList<String>(); // добавим в список ряд элементов states.add("Germany"); states.add("France"); states.addLast("Great Britain"); // добавляем на последнее место states.addFirst("Spain"); // добавляем на первое место states.add(1, "Italy"); // добавляем элемент по индексу 1 System.out.printf("List has %d elements \n", states.size()); System.out.println(states.get(1)); states.set(1, "Portugal"); for(String state : states){ System.out.println(state); } // проверка на наличие элемента в списке if(states.contains("Germany")){ System.out.println("List contains Germany"); } states.remove("Germany"); states.removeFirst(); // удаление первого элемента states.removeLast(); // удаление последнего элемента LinkedList<Person> people = new LinkedList<Person>(); people.add(new Person("Mike")); people.addFirst(new Person("Tom")); people.addLast(new Person("Nick")); people.remove(1); // удаление второго элемента for(Person p : people){ System.out.println(p.getName()); } Person first = people.getFirst(); System.out.println(first.getName()); // вывод первого элемента }}class Person{ private String name; public Person(String value){ name=value; } String getName(){return name;}} |
Здесь создаются и используются два списка: для строк и для объектов класса Person. При этом в дополнение к методам addFirst/removeLast и т.д.,
нам также доступны стандартные методы, определенные в интерфейсе Collection: add(), remove, contains,
size и другие. Поэтому мы можем использовать разные методы для одного и того же действия. Например, добавление в самое начало списка
можно сделать так: states.addFirst("Spain");, а можно сделать так: states.add(0, "Spain");
Интерфейс Set расширяет интерфейс Collection и представляет набор уникальных элементов. Set не добавляет новых методов, только вносит изменения в унаследованные. В частности, метод add() добавляет элемент в коллекцию и возвращает true, если в коллекции еще нет такого элемента.
Обобщенный класс HashSet представляет хеш-таблицу. Он наследует свой функционал от класса AbstractSet, а также реализует интерфейс Set.
Хеш-таблица представляет такую структуру данных, в которой все объекты имеют уникальный ключ или хеш-код. Данный ключ позволяет уникально идентифицировать объект в таблице.
Для создания объекта HashSet можно воспользоваться одним из следующих конструкторов:
HashSet(): создает пустой списокHashSet(Collection<? extends E> col): создает хеш-таблицу, в которую добавляет все элементы коллекции colHashSet(int capacity): параметр capacity указывает начальную емкость таблицы, которая по умолчанию равна 16HashSet(int capacity, float koef): параметр koef или коэффициент заполнения, значение которого должно быть в пределах от 0.0 до 1.0, указывает, насколько должна быть заполнена емкость объектами прежде чем произойдет ее расширение. Например, коэффициент 0.75 указывает, что при заполнении емкости на 3/4 произойдет ее расширение.
Класс HashSet не добавляет новых методов, реализуя лишь те, что объявлены в родительских классах и применяемых интерфейсах:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 | import java.util.HashSet;public class Program{ public static void main(String[] args) { HashSet<String> states = new HashSet<String>(); // добавим в список ряд элементов states.add("Germany"); states.add("France"); states.add("Italy"); // пытаемся добавить элемент, который уже есть в коллекции boolean isAdded = states.add("Germany"); System.out.println(isAdded); // false System.out.printf("Set contains %d elements \n", states.size()); // 3 for(String state : states){ System.out.println(state); } // удаление элемента states.remove("Germany"); // хеш-таблица объектов Person HashSet<Person> people = new HashSet<Person>(); people.add(new Person("Mike")); people.add(new Person("Tom")); people.add(new Person("Nick")); for(Person p : people){ System.out.println(p.getName()); } }}class Person{ private String name; public Person(String value){ name=value; } String getName(){return name;}} |
SortedSet
Интерфейс SortedSet предназначен для создания коллекций, который хранят элементы в отсортированном виде (сортировка по возрастанию). SortedSet расширяет интерфейс Set, поэтому такая коллекция опять же хранит только уникальные значения. SortedSet предоставляет следующие методы:
E first(): возвращает первый элемент набора
E last(): возвращает последний элемент набора
SortedSet<E> headSet(E end): возвращает объект SortedSet, который содержит все элементы первичного набора до элемента end
SortedSet<E> subSet(E start, E end): возвращает объект SortedSet, который содержит все элементы первичного набора между элементами start и end
SortedSet<E> tailSet(E start): возвращает объект SortedSet, который содержит все элементы первичного набора, начиная с элемента start
NavigableSet
Интерфейс NavigableSet расширяет интерфейс SortedSet и позволяет извлекать элементы на основании их значений. NavigableSet определяет следующие методы:
E ceiling(E obj): ищет в наборе наименьший элемент e, который больше obj (e >=obj). Если такой элемент найден, то он возвращается в качестве результата. Иначе возвращается null.
E floor(E obj): ищет в наборе наибольший элемент e, который меньше элемента obj (e <=obj). Если такой элемент найден, то он возвращается в качестве результата. Иначе возвращается null.
E higher(E obj): ищет в наборе наименьший элемент e, который больше элемента obj (e >obj). Если такой элемент найден, то он возвращается в качестве результата. Иначе возвращается null.
E lower(E obj): ищет в наборе наибольший элемент e, который меньше элемента obj (e <obj). Если такой элемент найден, то он возвращается в качестве результата. Иначе возвращается null.
E pollFirst(): возвращает первый элемент и удаляет его из набора
E pollLast(): возвращает последний элемент и удаляет его из набора
NavigableSet<E> descendingSet(): возвращает объект NavigableSet, который содержит все элементы первичного набора NavigableSet в обратном порядке
NavigableSet<E> headSet(E upperBound, boolean incl): возвращает объект NavigableSet, который содержит все элементы первичного набора NavigableSet до upperBound. Параметр incl при значении true, позволяет включить в выходной набор элемент upperBound
NavigableSet<E> tailSet(E lowerBound, boolean incl): возвращает объект NavigableSet, который содержит все элементы первичного набора NavigableSet, начиная с lowerBound. Параметр incl при значении true, позволяет включить в выходной набор элемент lowerBound
NavigableSet<E> subSet(E lowerBound, boolean lowerIncl, E upperBound, boolean highIncl): возвращает объект NavigableSet, который содержит все элементы первичного набора NavigableSet от lowerBound до upperBound.
TreeSet
Обобщенный класс TreeSet<E> представляет структуру данных в виде дерева, в котором все объекты хранятся в отсортированном виде по возрастанию.
TreeSet является наследником класса AbstractSet и реализует интерфейс NavigableSet, а следовательно, и интерфейс SortedSet.
В классе TreeSet определены следующие конструкторы:
TreeSet(): создает пустое деревоTreeSet(Collection<? extends E> col): создает дерево, в которое добавляет все элементы коллекции colTreeSet(SortedSet <E> set): создает дерево, в которое добавляет все элементы сортированного набора setTreeSet(Comparator<? super E> comparator): создает пустое дерево, где все добавляемые элементы впоследствии будут отсортированы компаратором.
TreeSet поддерживает все стандартные методы для вставки и удаления элементов:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 | import java.util.TreeSet;public class Program{ public static void main(String[] args) { TreeSet<String> states = new TreeSet<String>(); // добавим в список ряд элементов states.add("Germany"); states.add("France"); states.add("Italy"); states.add("Great Britain"); System.out.printf("TreeSet contains %d elements \n", states.size()); // удаление элемента states.remove("Germany"); for(String state : states){ System.out.println(state); } }} |
И поскольку при вставке объекты сразу же сортируются по возрастанию, то при выводе в цикле for мы получим отсортированный набор:
TreeSet contains 4 elements France Great Britain Italy
Так как TreeSet реализует интерфейс NavigableSet, а через него и SortedSet, то мы можем применить к структуре дерева различные методы:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 | import java.util.*;public class Program{ public static void main(String[] args) { TreeSet<String> states = new TreeSet<String>(); // добавим в список ряд элементов states.add("Germany"); states.add("France"); states.add("Italy"); states.add("Spain"); states.add("Great Britain"); System.out.println(states.first()); // получим первый - самый меньший элемент System.out.println(states.last()); // получим последний - самый больший элемент // получим поднабор от одного элемента до другого SortedSet<String> set = states.subSet("Germany", "Italy"); System.out.println(set); // элемент из набора, который больше текущего String greater = states.higher("Germany"); // элемент из набора, который меньше текущего String lower = states.lower("Germany"); // возвращаем набор в обратном порядке NavigableSet<String> navSet = states.descendingSet(); // возвращаем набор в котором все элементы меньше текущего SortedSet<String> setLower=states.headSet("Germany"); // возвращаем набор в котором все элементы больше текущего SortedSet<String> setGreater=states.tailSet("Germany"); System.out.println(navSet); System.out.println(setLower); System.out.println(setGreater); }} |
В прошлой теме была рассмотрена работа коллекции TreeSet, типизированной объектами String. При добавлении новых элементов объект TreeSet автоматически проводит сортировку, помещая новый объект на правильное для него место. Однако со строками все понятно. А что если бы мы использовали не строки, а свои классы, например, следующий класс Person:
1 2 3 4 5 6 7 8 9 | class Person{ private String name; Person(String name){ this.name=name; } String getName(){return name;}} |
Объект TreeSet мы не сможем типизировать данным классом, поскольку в случае добавления объектов TreeSet не будет знать, как их сравнивать, и следующий кусок кода не будет работать:
1 2 | TreeSet<Person> people = new TreeSet<Person>();people.add(new Person("Tom")); |
При выполнении этого кода мы столкнемся с ошибкой, которая скажет, что объект Person не может быть преобразован к типу java.lang.Comparable.
Для того, чтобы объекты Person можно было сравнить и сортировать, они должны применять интерфейс Comparable<E>. При применении интерфейса он типизируется текущим классом. Применим его к классу Person:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | class Person implements Comparable<Person>{ private String name; Person(String name){ this.name = name; } String getName(){return name;} public int compareTo(Person p){ return name.compareTo(p.getName()); }} |
Интерфейс Comparable содержит один единственный метод int compareTo(E item), который сравнивает текущий объект с объектом, переданным в качестве
параметра. Если этот метод возвращает отрицательное число, то текущий объект будет располагаться перед тем, который передается через параметр. Если
метод вернет положительное число, то, наоборот, после второго объекта. Если метод возвратит ноль, значит, оба объекта равны.
В данном случае мы не возвращаем явным образом никакое число, а полагаемся на встроенный механизм сравнения, который есть у класса String. Но мы также можем определить и свою логику, например, сравнивать по длине имени:
1 2 3 4 | public int compareTo(Person p){ return name.length()-p.getName().length();} |
Теперь мы можем типизировать TreeSet типом Person и добавлять в дерево соответствующие объекты:
1 2 | TreeSet<Person> people = new TreeSet<Person>();people.add(new Person("Tom")); |
Интерфейс Comparator
Однако перед нами может возникнуть проблема, что если разработчик не реализовал в своем классе, который мы хотим использовать, интерфейс Comparable, либо реализовал, но нас не устраивает его функциональность, и мы хотим ее переопределить? На этот случай есть еще более гибкий способ, предполагающий применение интерфейса Comparator<E>.
Интерфейс Comparator содержит ряд методов, ключевым из которых является метод compare():
1 2 3 4 5 | public interface Comparator<E> { int compare(T a, T b); // остальные методы} |
Метод compare также возвращает числовое значение - если оно отрицательное, то объект a предшествует объекту b, иначе - наоборот.
А если метод возвращает ноль, то объекты равны. Для применения интерфейса нам вначале надо создать класс компаратора, который реализует этот интерфейс:
1 2 3 4 5 6 7 | class PersonComparator implements Comparator<Person>{ public int compare(Person a, Person b){ return a.getName().compareTo(b.getName()); }} |
Здесь опять же проводим сравнение по строкам. Теперь используем класс компаратора для создания объекта TreeSet:
1 2 3 4 5 6 7 8 9 10 | PersonComparator pcomp = new PersonComparator();TreeSet<Person> people = new TreeSet<Person>(pcomp);people.add(new Person("Tom"));people.add(new Person("Nick"));people.add(new Person("Alice"));people.add(new Person("Bill"));for(Person p : people){ System.out.println(p.getName());} |
Для создания TreeSet здесь используется одна из версий конструктора, которая в качестве параметра принимает компаратор. Теперь вне зависимости от того, реализован ли в классе Person интерфейс Comparable, логика сравнения и сортировки будет использоваться та, которая определена в классе компаратора.
Сортировка по нескольким критериям
Начиная с JDK 8 в механизм работы компараторов были внесены некоторые дополнения. В частности, теперь мы можем применять сразу несколько компараторов по принципу приоритета. Например, изменим класс Person следующим образом:
1 2 3 4 5 6 7 8 9 10 11 12 | class Person{ private String name; private int age; public Person(String n, int a){ name=n; age=a; } String getName(){return name;} int getAge(){return age;}} |
Здесь добавлено поле для хранения возраста пользователя. И, допустим, нам надо отсортировать пользователей по имени и по возрасту. Для этого определим два компаратора:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 | class PersonNameComparator implements Comparator<Person>{ public int compare(Person a, Person b){ return a.getName().compareTo(b.getName()); }}class PersonAgeComparator implements Comparator<Person>{ public int compare(Person a, Person b){ if(a.getAge()> b.getAge()) return 1; else if(a.getAge()< b.getAge()) return -1; else return 0; }} |
Интерфейс компаратора определяет специальный метод по умолчанию thenComparing, который позволяет использовать цепочки компараторов для сортировки набора:
1 2 3 4 5 6 7 8 9 10 11 | Comparator<Person> pcomp = new PersonNameComparator().thenComparing(new PersonAgeComparator());TreeSet<Person> people = new TreeSet(pcomp);people.add(new Person("Tom", 23));people.add(new Person("Nick",34));people.add(new Person("Tom",10));people.add(new Person("Bill",14));for(Person p : people){ System.out.println(p.getName() + " " + p.getAge());} |
Консольный вывод:
Bill 14 Nick 34 Tom 10 Tom 23
В данном случае сначала применяется сортировка по имени, а потом по возрасту.
Интерфейс Map<K, V> представляет отображение или иначе говоря словарь, где каждый элемент представляет пару "ключ-значение". При этом все ключи уникальные в рамках объекта Map. Такие коллекции облегчают поиск элемента, если нам известен ключ - уникальный идентификатор объекта.
Следует отметить, что в отличие от других интерфейсов, которые представляют коллекции, интерфейс Map НЕ расширяет интерфейс Collection.
Среди методов интерфейса Map можно выделить следующие:
void clear(): очищает коллекциюboolean containsKey(Object k): возвращает true, если коллекция содержит ключ kboolean containsValue(Object v): возвращает true, если коллекция содержит значение vSet<Map.Entry<K, V>> entrySet(): возвращает набор элементов коллекции. Все элементы представляют объектMap.Entryboolean equals(Object obj): возвращает true, если коллекция идентична коллекции, передаваемой через параметр objboolean isEmpty: возвращает true, если коллекция пустаV get(Object k): возвращает значение объекта, ключ которого равен k. Если такого элемента не окажется, то возвращается значениеnullV getOrDefault(Object k, V defaultValue): возвращает значение объекта, ключ которого равен k. Если такого элемента не окажется, то возвращается значениеdefaultVlueV put(K k, V v): помещает в коллекцию новый объект с ключом k и значением v. Если в коллекции уже есть объект с подобным ключом, то он перезаписывается. После добавления возвращает предыдущее значение для ключа k, если он уже был в коллекции. Если же ключа еще не было в коллекции, то возвращается значениеnullV putIfAbsent(K k, V v): помещает в коллекцию новый объект с ключом k и значением v, если в коллекции еще нет элемента с подобным ключом.Set<K> keySet(): возвращает набор всех ключей отображенияCollection<V> values(): возвращает набор всех значений отображенияvoid putAll(Map<? extends K, ? extends V> map): добавляет в коллекцию все объекты из отображения mapV remove(Object k): удаляет объект с ключом kint size(): возвращает количество элементов коллекции
Чтобы положить объект в коллекцию, используется метод put, а чтобы получить по ключу - метод get. Реализация интерфейса
Map также позволяет получить наборы как ключей, так и значений. А метод entrySet() возвращает набор всех элементов в виде объектов
Map.Entry<K, V>.
Обобщенный интерфейс Map.Entry<K, V> представляет объект с ключом типа K и значением типа V и определяет следующие методы:
boolean equals(Object obj): возвращает true, если объект obj, представляющий интерфейсMap.Entry, идентичен текущемуK getKey(): возвращает ключ объекта отображенияV getValue(): возвращает значение объекта отображенияV setValue(V v): устанавливает для текущего объекта значение vint hashCode(): возвращает хеш-код данного объекта
При переборе объектов отображения мы будем оперировать этими методами для работы с ключами и значениями объектов.
Классы отображений. HashMap
Базовым классом для всех отображений является абстрактный класс AbstractMap, который реализует большую часть методов интерфейса Map. Наиболее распространенным классом отображений является HashMap, который реализует интерфейс Map и наследуется от класса AbstractMap.
Пример использования класса:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 | import java.util.*;public class Program{ public static void main(String[] args) { Map<Integer, String> states = new HashMap<Integer, String>(); states.put(1, "Germany"); states.put(2, "Spain"); states.put(4, "France"); states.put(3, "Italy"); // получим объект по ключу 2 String first = states.get(2); System.out.println(first); // получим весь набор ключей Set<Integer> keys = states.keySet(); // получить набор всех значений Collection<String> values = states.values(); //заменить элемент states.replace(1, "Poland"); // удаление элемента по ключу 2 states.remove(2); // перебор элементов for(Map.Entry<Integer, String> item : states.entrySet()){ System.out.printf("Key: %d Value: %s \n", item.getKey(), item.getValue()); } Map<String, Person> people = new HashMap<String, Person>(); people.put("1240i54", new Person("Tom")); people.put("1564i55", new Person("Bill")); people.put("4540i56", new Person("Nick")); for(Map.Entry<String, Person> item : people.entrySet()){ System.out.printf("Key: %s Value: %s \n", item.getKey(), item.getValue().getName()); } }}class Person{ private String name; public Person(String value){ name=value; } String getName(){return name;}} |
Чтобы добавить или заменить элемент, используется метод put, либо replace, а чтобы получить его значение по ключу - метод get. С помощью других методов интерфейса Map также производятся другие манипуляции над элементами: перебор, получение ключей, значений, удаление.
Для создания отображений Java также предоставляет ряд дополнительных интерфейсов: SortedMap и NavigableMap
SortedMap
Интерфейс SortedMap расширяет Map и создает отображение, в котором все элементы отсортированы в порядке возрастания их ключей. SortedMap добавляет ряд методов:
K firstKey(): возвращает ключ первого элемента отображенияK lastKey(): возвращает ключ последнего элемента отображенияSortedMap<K, V> headMap(K end): возвращает отображение SortedMap, которые содержит все элементы оригинального SortedMap вплоть до элемента с ключом endSortedMap<K, V> tailMap(K start): возвращает отображение SortedMap, которые содержит все элементы оригинального SortedMap, начиная с элемента с ключом startSortedMap<K, V> subMap(K start, K end): возвращает отображение SortedMap, которые содержит все элементы оригинального SortedMap вплоть от элемента с ключом start до элемента с ключом end
NavigableMap
Интерфейс NavigableMap расширяет интерфейс SortedMap и обеспечивает возможность получения элементов отображения относительно других элементов. Его основные методы:
Map.Entry<K, V> ceilingEntry(K key): возвращает элемент с наименьшим ключом k, который больше или равен ключу key (k >=key). Если такого ключа нет, то возвращается null.Map.Entry<K, V> floorEntry(K key): возвращает элемент с наибольшим ключом k, который меньше или равен ключу key (k <=key). Если такого ключа нет, то возвращается null.Map.Entry<K, V> higherEntry(K key): возвращает элемент с наименьшим ключом k, который больше ключа key (k >key). Если такого ключа нет, то возвращается null.Map.Entry<K, V> lowerEntry(K key): возвращает элемент с наибольшим ключом k, который меньше ключа key (k <key). Если такого ключа нет, то возвращается null.Map.Entry<K, V> firstEntry(): возвращает первый элемент отображенияMap.Entry<K, V> lastEntry(): возвращает последний элемент отображенияMap.Entry<K, V> pollFirstEntry(): возвращает и одновременно удаляет первый элемент из отображенияMap.Entry<K, V> pollLastEntry(): возвращает и одновременно удаляет последний элемент из отображенияK ceilingKey(K key): возвращает наименьший ключ k, который больше или равен ключу key (k >=key). Если такого ключа нет, то возвращается null.K floorKey(K key): возвращает наибольший ключ k, который меньше или равен ключу key (k <=key). Если такого ключа нет, то возвращается null.K lowerKey(K key): возвращает наибольший ключ k, который меньше ключа key (k <key). Если такого ключа нет, то возвращается null.K higherKey(K key): возвращает наименьший ключ k, который больше ключа key (k >key). Если такого ключа нет, то возвращается null.NavigableSet<K> descendingKeySet(): возвращает объект NavigableSet, который содержит все ключи отображения в обратном порядкеNavigableMap<K, V> descendingMap(): возвращает отображение NavigableMap, которое содержит все элементы в обратном порядкеNavigableSet<K> navigableKeySet(): возвращает объект NavigableSet, который содержит все ключи отображенияNavigableMap<K, V> headMap(K upperBound, boolean incl): возвращает отображение NavigableMap, которое содержит все элементы оригинального NavigableMap вплоть от элемента с ключом upperBound. Параметр incl при значении true указывает, что элемент с ключом upperBound также включается в выходной набор.NavigableMap<K, V> tailMap(K lowerBound, boolean incl): возвращает отображение NavigableMap, которое содержит все элементы оригинального NavigableMap, начиная с элемента с ключом lowerBound. Параметр incl при значении true указывает, что элемент с ключом lowerBound также включается в выходной набор.NavigableMap<K, V> subMap(K lowerBound, boolean lowIncl, K upperBound, boolean highIncl): возвращает отображение NavigableMap, которое содержит все элементы оригинального NavigableMap от элемента с ключом lowerBound до элемента с ключом upperBound. Параметры lowIncl и highIncl при значении true включают в выходной набор элементы с ключами lowerBound и upperBound соответственно.
TreeMap
Класс TreeMap<K, V> представляет отображение в виде дерева. Он наследуется от класса AbstractMap и реализует интерфейс NavigableMap, а следовательно, также и интерфейс SortedMap. Поэтому в отличие от коллекции HashMap в TreeMap все объекты автоматически сортируются по возрастанию их ключей.
Класс TreeMap имеет следующие конструкторы:
TreeMap(): создает пустое отображение в виде дереваTreeMap(Map<? extends K,? extends V> map): создает дерево, в которое добавляет все элементы из отображения mapTreeMap(SortedMap<K, ? extends V> smap): создает дерево, в которое добавляет все элементы из отображения smapTreeMap(Comparator<? super K> comparator): создает пустое дерево, где все добавляемые элементы впоследствии будут отсортированы компаратором.
Используем класс в программе:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 | import java.util.*;public class Program{ public static void main(String[] args) { TreeMap<Integer, String> states = new TreeMap<Integer, String>(); states.put(10, "Germany"); states.put(2, "Spain"); states.put(14, "France"); states.put(3, "Italy"); // получим объект по ключу 2 String first = states.get(2); // перебор элементов for(Map.Entry<Integer, String> item : states.entrySet()){ System.out.printf("Key: %d Value: %s \n", item.getKey(), item.getValue()); } // получим весь набор ключей Set<Integer> keys = states.keySet(); // получить набор всех значений Collection<String> values = states.values(); // получаем все объекты, которые стоят после объекта с ключом 4 Map<Integer, String> afterMap = states.tailMap(4); // получаем все объекты, которые стоят до объекта с ключом 10 Map<Integer, String> beforeMap = states.headMap(10); // получим последний элемент дерева Map.Entry<Integer, String> lastItem = states.lastEntry(); System.out.printf("Last item has key %d value %s \n",lastItem.getKey(), lastItem.getValue()); Map<String, Person> people = new TreeMap<String, Person>(); people.put("1240i54", new Person("Tom")); people.put("1564i55", new Person("Bill")); people.put("4540i56", new Person("Nick")); for(Map.Entry<String, Person> item : people.entrySet()){ System.out.printf("Key: %s Value: %s \n", item.getKey(), item.getValue().getName()); } }}class Person{ private String name; public Person(String name){ this.name = name; } String getName(){return name;}} |
Кроме собственно методов интерфейса Map класс TreeMap реализует методы интерфейса NavigableMap. Например, мы можем получить
все объекты до или после определенного ключа с помощью методов headMap и tailMap. Также мы можем получить первый и последний элементы
и провести ряд дополнительных манипуляций с объектами.
Коллекции
11. КОЛЛЕКЦИИ
Базовые задачи:
Создание списка: Создайте
ArrayListи добавьте несколько элементов.- Решение:java
List<String> list = new ArrayList<>(); list.add("Element 1"); list.add("Element 2");
- Решение:
Итерация по списку: Пройдите по элементам
ArrayListс помощью циклаfor-each.- Решение:java
for (String element : list) { System.out.println(element); }
- Решение:
Удаление элемента из списка: Удалите элемент из
ArrayList.- Решение:java
list.remove("Element 1");
- Решение:
Создание карты: Создайте
HashMapи добавьте пары ключ-значение.- Решение:java
Map<Integer, String> map = new HashMap<>(); map.put(1, "Value 1"); map.put(2, "Value 2");
- Решение:
Итерация по карте: Пройдите по парам ключ-значение в
HashMap.- Решение:java
for (Map.Entry<Integer, String> entry : map.entrySet()) { System.out.println(entry.getKey() + ": " + entry.getValue()); }
- Решение:
Сложные задачи:
Использование
Set: СоздайтеHashSetи добавьте несколько элементов.- Решение:java
Set<String> set = new HashSet<>(); set.add("Element 1"); set.add("Element 2");
- Решение:
Преобразование списка в массив: Преобразуйте
ArrayListв массив.- Решение:java
String[] array = list.toArray(new String[0]);
- Решение:
Сортировка списка: Отсортируйте
ArrayListс помощьюCollections.sort().- Решение:java
Collections.sort(list);
- Решение:
Фильтрация коллекций: Используйте
Streamдля фильтрации элементов в списке.- Решение:java
List<String> filtered = list.stream() .filter(s -> s.startsWith("E")) .collect(Collectors.toList());
- Решение:
Объединение коллекций: Объедините два списка в один.
- Решение:java
List<String> list1 = new ArrayList<>(); List<String> list2 = new ArrayList<>(); list1.addAll(list2);
- Решение:
12. JAVA STREAM API
Базовые задачи:
Создание стрима из списка: Создайте
StreamизArrayList.- Решение:java
Stream<String> stream = list.stream();
- Решение:
Фильтрация элементов: Используйте
filter()для получения элементов, которые соответствуют условию.- Решение:java
List<String> filteredList = list.stream() .filter(s -> s.startsWith("E")) .collect(Collectors.toList());
- Решение:
Преобразование элементов: Используйте
map()для преобразования элементов в другой тип.- Решение:java
List<Integer> lengths = list.stream() .map(String::length) .collect(Collectors.toList());
- Решение:
Сортировка элементов: Используйте
sorted()для сортировки элементов в стриме.- Решение:java
List<String> sortedList = list.stream() .sorted() .collect(Collectors.toList());
- Решение:
Получение уникальных элементов: Используйте
distinct()для получения уникальных элементов.- Решение:java
List<String> uniqueList = list.stream() .distinct() .collect(Collectors.toList());
- Решение:
Сложные задачи:
Аггрегация элементов: Используйте
reduce()для агрегации элементов.- Решение:java
Optional<String> concatenated = list.stream() .reduce((s1, s2) -> s1 + s2);
- Решение:
Группировка элементов: Используйте
Collectors.groupingBy()для группировки элементов.- Решение:java
Map<Integer, List<String>> groupedByLength = list.stream() .collect(Collectors.groupingBy(String::length));
- Решение:
Подсчет элементов: Используйте
count()для подсчета количества элементов.- Решение:java
long count = list.stream().count();
- Решение:
Сбор элементов в карту: Используйте
Collectors.toMap()для создания карты.- Решение:java
Map<Integer, String> map = list.stream() .collect(Collectors.toMap(String::length, Function.identity()));
- Решение:
Обработка сложных объектов: Создайте класс и примените
Streamк коллекции объектов.- Решение:java
class Person { String name; int age; // конструктор и геттеры } List<Person> people = Arrays.asList(new Person("Alice", 30), new Person("Bob", 20)); List<String> names = people.stream() .map(Person::getName) .collect(Collectors.toList());
- Решение:
13. JAVA 8 НОВШЕСТВА
Базовые задачи:
Лямбда-выражения: Создайте лямбда-выражение для интерфейса с одним методом.
- Решение:java
@FunctionalInterface interface MyFunctionalInterface { void myMethod(); } MyFunctionalInterface myLambda = () -> System.out.println("Hello from lambda!");
- Решение:
Использование Stream API: Создайте стрим из списка и выполните некоторые операции.
- Решение:java
List<String> list = Arrays.asList("A", "B", "C"); list.stream().forEach(System.out::println);
- Решение:
Ссылки на методы: Используйте ссылку на метод вместо лямбда-выражения.
- Решение:java
list.forEach(System.out::println);
- Решение:
Создание интерфейса с несколькими методами: Создайте интерфейс с несколькими методами и используйте его с лямбда-выражением.
- Решение:java
@FunctionalInterface interface MultiFunctionalInterface { void method1(); void method2(); } MultiFunctionalInterface myMultiLambda = new MultiFunctionalInterface() { public void method1() { System.out.println("Method 1"); } public void method2() { System.out.println("Method 2"); } };
- Решение:
Обработка ошибок с помощью лямбда-выражений: Используйте лямбда-выражения для обработки ошибок.
- Решение:java
BiConsumer<Integer, Integer> divide = (a, b) -> { try { System.out.println(a / b); } catch (ArithmeticException e) { System.out.println("Cannot divide by zero!"); } };
- Решение:
Сложные задачи:
Применение Optional: Используйте
Optionalдля предотвращенияNullPointerException.- Решение:java
Optional<String> optional = Optional.ofNullable(null); optional.ifPresent(System.out::println);
- Решение:
Обработка коллекций с помощью Stream API: Используйте
Streamдля фильтрации и обработки коллекций.- Решение:java
List<String> filteredList = list.stream() .filter(s -> s.startsWith("A")) .collect(Collectors.toList());
- Решение:
Группировка с использованием Stream API: Группируйте элементы в списке по определенному критерию.
- Решение:java
Map<Integer, List<String>> grouped = list.stream() .collect(Collectors.groupingBy(String::length));
- Решение:
Использование Stream API для создания объектов: Создайте коллекцию объектов с помощью Stream API.
- Решение:java
List<Person> people = Arrays.asList("Alice", "Bob").stream() .map(name -> new Person(name, name.length())) .collect(Collectors.toList());
- Решение:
Использование лямбда-выражений в методах: Передавайте лямбда-выражения в методы как параметры.
- Решение:java
void execute(Runnable runnable) { runnable.run(); } execute(() -> System.out.println("Running a lambda!"));
- Решение:
14. JAVAFX
Базовые задачи:
Создание окна JavaFX: Создайте базовое окно JavaFX.
- Решение:java
import javafx.application.Application; import javafx.scene.Scene; import javafx.scene.control.Button; import javafx.scene.layout.StackPane; import javafx.stage.Stage; public class MyApp extends Application { @Override public void start(Stage primaryStage) { Button btn = new Button("Click me"); StackPane root = new StackPane(); root.getChildren().add(btn); Scene scene = new Scene(root, 300, 250); primaryStage.setTitle("JavaFX App"); primaryStage.setScene(scene); primaryStage.show(); } public static void main(String[] args) { launch(args); } }
- Решение:
Добавление событий: Обработайте нажатие кнопки.
- Решение:java
btn.setOnAction(event -> System.out.println("Button clicked!"));
- Решение:
Изменение стиля: Измените стиль кнопки с помощью CSS.
- Решение:css
.button { -fx-background-color: blue; -fx-text-fill: white; }
- Решение:
Использование различных контейнеров: Используйте
VBoxиHBoxдля размещения элементов.- Решение:java
VBox vbox = new VBox(); HBox hbox = new HBox();
- Решение:
Создание меню: Создайте простое меню в приложении.
- Решение:java
MenuBar menuBar = new MenuBar(); Menu menu = new Menu("File"); MenuItem menuItem = new MenuItem("Exit"); menu.getItems().add(menuItem); menuBar.getMenus().add(menu);
- Решение:
Сложные задачи:
Использование таблицы: Создайте таблицу с данными.
- Решение:java
TableView<Person> table = new TableView<>(); TableColumn<Person, String> nameColumn = new TableColumn<>("Name"); table.getColumns().add(nameColumn);
- Решение:
Создание графиков: Создайте простой график.
- Решение:java
XYChart.Series<String, Number> series = new XYChart.Series<>(); series.getData().add(new XYChart.Data<>("2021", 200));
- Решение:
Работа с изображениями: Отобразите изображение в приложении.
- Решение:java
Image image = new Image("image.png"); ImageView imageView = new ImageView(image);
- Решение:
Анимации: Создайте простую анимацию.
- Решение:java
TranslateTransition transition = new TranslateTransition(); transition.setNode(btn); transition.setToX(100); transition.play();
- Решение:
Работа с диалогами: Создайте диалоговое окно.
- Решение:java
Alert alert = new Alert(Alert.AlertType.INFORMATION); alert.setTitle("Info Dialog"); alert.setHeaderText(null); alert.setContentText("This is an information dialog."); alert.showAndWait();
- Решение:
Оператор throws
Иногда метод, в котором может генерироваться исключение, сам не обрабатывает это исключение. В этом случае в объявлении метода используется оператор throws, который надо обработать при вызове этого метода. Например, у нас имеется метод вычисления факториала, и нам надо обработать ситуацию, если в метод передается число меньше 1:
1 2 3 4 5 6 7 8 9 10 | public static int getFactorial(int num) throws Exception{ if(num<1) throw new Exception("The number is less than 1"); int result=1; for(int i=1; i<=num;i++){ result*=i; } return result;} |
С помощью оператора throw по условию выбрасывается исключение. В то же время метод сам это исключение не обрабатывает с помощью
try..catch, поэтому в определении метода используется выражение throws Exception.
Теперь при вызове этого метода нам обязательно надо обработать выбрасываемое исключение:
1 2 3 4 5 6 7 8 9 10 11 12 | public static void main(String[] args){ try{ int result = getFactorial(-6); System.out.println(result); } catch(Exception ex){ System.out.println(ex.getMessage()); }} |
Без обработки исключение у нас возникнет ошибка компиляции, и мы не сможем скомпилировать программу.
В качестве альтернативы мы могли бы и не использовать оператор throws, а обработать исключение прямо в методе:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 | public static int getFactorial(int num){ int result=1; try{ if(num<1) throw new Exception("The number is less than 1"); for(int i=1; i<=num;i++){ result*=i; } } catch(Exception ex){ System.out.println(ex.getMessage()); result=num; } return result;} |
Базовым классом для всех исключений является класс Throwable. От него уже наследуются два класса: Error и Exception. Все остальные классы являются производными от этих двух классов.
Класс Error описывает внутренние ошибки в исполняющей среде Java. Программист имеет очень ограниченные возможности для обработки подобных ошибок.
Собственно исключения наследуются от класса Exception. Среди этих исключений следует выделить класс RuntimeException. RuntimeException является базовым классом для так называемой группы непроверяемых исключений (unchecked exceptions) - компилятор не проверяет факт обработки таких исключений и их можно не указывать вместе с оператором throws в объявлении метода. Такие исключения являются следствием ошибок разработчика, например, неверное преобразование типов или выход за пределы массива.
Некоторые из классов непроверяемых исключений:
ArithmeticException: исключение, возникающее при делении на ноль
IndexOutOfBoundException: индекс вне границ массива
IllegalArgumentException: использование неверного аргумента при вызове метода
NullPointerException: использование пустой ссылки
NumberFormatException: ошибка преобразования строки в число
Все остальные классы, образованные от класса Exception, называются проверяемыми исключениями (checked exceptions).
Некоторые из классов проверяемых исключений:
CloneNotSupportedException: класс, для объекта которого вызывается клонирование, не реализует интерфейс Cloneable
InterruptedException: поток прерван другим потоком
ClassNotFoundException: невозможно найти класс
Подобные исключения обрабатываются с помощью конструкции try..catch. Либо можно передать обработку методу, который будет вызывать данный метод, указав исключения после оператора throws:
1 2 3 4 5 | public Person clone() throws CloneNotSupportedException{ Person p = (Person) super.clone(); return p;} |
В итоге получается следующая иерархия исключений:
Поскольку все классы исключений наследуются от класса Exception, то все они наследуют ряд его методов, которые позволяют получить информацию о характере исключения. Среди этих методов отметим наиболее важные:
Метод getMessage() возвращает сообщение об исключении
Метод getStackTrace() возвращает массив, содержащий трассировку стека исключения
Метод printStackTrace() отображает трассировку стека
Например:
1 2 3 4 5 6 7 | try{ int x = 6/0;}catch(Exception ex){ ex.printStackTrace();} |
Хотя имеющиеся в стандартной библиотеке классов Java классы исключений описывают большинство исключительных ситуаций, которые могут возникнуть при выполнении программы, все таки иногда требуется создать свои собственные классы исключений со своей логикой.
Чтобы создать свой класс исключений, надо унаследовать его от класса Exception. Например, у нас есть класс, вычисляющий факториал, и нам надо выбрасывать специальное исключение, если число, передаваемое в метод, меньше 1:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 | class Factorial{ public static int getFactorial(int num) throws FactorialException{ int result=1; if(num<1) throw new FactorialException("The number is less than 1", num); for(int i=1; i<=num;i++){ result*=i; } return result; }}class FactorialException extends Exception{ private int number; public int getNumber(){return number;} public FactorialException(String message, int num){ super(message); number=num; }} |
Здесь для определения ошибки, связанной с вычислением факториала, определен класс FactorialException, который наследуется от Exception
и который содержит всю информацию о вычислении. В конструкторе FactorialException в конструктор базового класса Exception передается сообщение об ошибке:
super(message). Кроме того, отдельное поле предназначено для хранения числа, факториал которого вычисляется.
Для генерации исключения в методе вычисления факториала выбрасывается исключение с помощью оператора throw: throw new FactorialException("Число не может быть меньше 1", num).
Кроме того, так как это исключение не обрабатывается с помощью try..catch, то мы передаем обработку вызывающему методу, используя оператор throws:
public static int getFactorial(int num) throws FactorialException
Теперь используем класс в методе main:
1 2 3 4 5 6 7 8 9 10 11 12 | public static void main(String[] args){ try{ int result = Factorial.getFactorial(6); System.out.println(result); } catch(FactorialException ex){ System.out.println(ex.getMessage()); System.out.println(ex.getNumber()); }} |
Обработка исключений
ОПЕРАТОР THROWS
Базовые задачи:
Создание метода с
throws: Напишите метод, который генерирует исключениеArithmeticException.- Решение:java
public void divide(int a, int b) throws ArithmeticException { if (b == 0) { throw new ArithmeticException("Cannot divide by zero"); } System.out.println(a / b); } - Входные данные:java
divide(10, 0); // вызовет исключение
- Решение:
Обработка
throws: Создайте метод, который вызывает другой метод с операторомthrows.- Решение:java
public void process() throws ArithmeticException { divide(10, 0); } - Входные данные:java
try { process(); } catch (ArithmeticException e) { System.out.println(e.getMessage()); }
- Решение:
Каскадное исключение: Создайте метод, который вызывает метод с
throws, и обработайте исключение в вызывающем методе.- Решение:java
public void invoke() throws ArithmeticException { process(); } - Входные данные:java
try { invoke(); } catch (ArithmeticException e) { System.out.println(e.getMessage()); }
- Решение:
Проверка исключения: Создайте метод, который проверяет ввод и выбрасывает исключение, если он некорректен.
- Решение:java
public void validateInput(int value) throws IllegalArgumentException { if (value < 0) { throw new IllegalArgumentException("Value must be non-negative"); } } - Входные данные:java
validateInput(-5); // вызовет исключение
- Решение:
Множественные исключения: Напишите метод, который может выбрасывать несколько исключений.
- Решение:java
public void check(int a, int b) throws ArithmeticException, IllegalArgumentException { if (b == 0) { throw new ArithmeticException("Cannot divide by zero"); } validateInput(a); } - Входные данные:java
try { check(5, 0); } catch (Exception e) { System.out.println(e.getMessage()); }
- Решение:
Сложные задачи:
Использование
throwsс несколькими методами: Создайте цепочку методов, где каждый метод выбрасывает исключение.- Решение:java
public void firstMethod() throws ArithmeticException { secondMethod(); } public void secondMethod() throws ArithmeticException { divide(10, 0); } - Входные данные:java
try { firstMethod(); } catch (ArithmeticException e) { System.out.println(e.getMessage()); }
- Решение:
Логирование исключений: Создайте метод, который обрабатывает исключение и записывает его в лог.
- Решение:java
public void logException() { try { divide(10, 0); } catch (ArithmeticException e) { System.out.println("Logging error: " + e.getMessage()); } } - Входные данные:java
logException();
- Решение:
Передача исключений: Напишите метод, который выбрасывает исключение, и вызовите его в другом методе.
- Решение:java
public void throwError() throws Exception { throw new Exception("An error occurred"); } public void callError() { try { throwError(); } catch (Exception e) { System.out.println(e.getMessage()); } } - Входные данные:java
callError();
- Решение:
Обработка нескольких типов исключений: Создайте метод, который обрабатывает несколько типов исключений.
- Решение:java
public void processMultiple() { try { validateInput(-1); divide(10, 0); } catch (IllegalArgumentException | ArithmeticException e) { System.out.println(e.getMessage()); } } - Входные данные:java
processMultiple();
- Решение:
Создание обработчика исключений: Создайте обработчик для специфических исключений.
- Решение:java
public void customHandler(Exception e) { System.out.println("Custom Handler: " + e.getMessage()); } public void invokeHandler() { try { divide(10, 0); } catch (Exception e) { customHandler(e); } } - Входные данные:java
invokeHandler();
- Решение:
КЛАССЫ ИСКЛЮЧЕНИЙ
Базовые задачи:
Создание стандартного исключения: Напишите метод, который выбрасывает стандартное исключение.
- Решение:java
public void throwStandardException() { throw new NullPointerException("Null pointer exception thrown"); } - Входные данные:java
try { throwStandardException(); } catch (NullPointerException e) { System.out.println(e.getMessage()); }
- Решение:
Проверка исключения: Напишите метод, который выбрасывает
ArrayIndexOutOfBoundsException.- Решение:java
public void checkArrayIndex(int[] arr, int index) { if (index >= arr.length) { throw new ArrayIndexOutOfBoundsException("Index out of bounds"); } } - Входные данные:java
int[] array = {1, 2, 3}; checkArrayIndex(array, 5); // вызовет исключение
- Решение:
Использование
NumberFormatException: Напишите метод, который выбрасываетNumberFormatException.- Решение:java
public void parseNumber(String number) { try { Integer.parseInt(number); } catch (NumberFormatException e) { throw new NumberFormatException("Invalid number format"); } } - Входные данные:java
parseNumber("abc"); // вызовет исключение
- Решение:
Обработка
IOException: Создайте метод, который выбрасываетIOException.- Решение:java
public void readFile() throws IOException { throw new IOException("File not found"); } - Входные данные:java
try { readFile(); } catch (IOException e) { System.out.println(e.getMessage()); }
- Решение:
Использование
ClassNotFoundException: Напишите метод, который выбрасываетClassNotFoundException.- Решение:java
public void loadClass() throws ClassNotFoundException { throw new ClassNotFoundException("Class not found"); } - Входные данные:java
try { loadClass(); } catch (ClassNotFoundException e) { System.out.println(e.getMessage()); }
- Решение:
Сложные задачи:
Создание иерархии исключений: Создайте свою иерархию классов исключений.
- Решение:java
class CustomException extends Exception { public CustomException(String message) { super(message); } } class SpecificException extends CustomException { public SpecificException(String message) { super(message); } } - Входные данные:java
public void throwCustomException() throws SpecificException { throw new SpecificException("This is a specific exception"); } try { throwCustomException(); } catch (SpecificException e) { System.out.println(e.getMessage()); }
- Решение:
Кастомизация исключений: Создайте класс исключения с дополнительными полями.
- Решение:java
class DetailedException extends Exception { private int errorCode; public DetailedException(String message, int errorCode) { super(message); this.errorCode = errorCode; } public int getErrorCode() { return errorCode; } } - Входные данные:java
public void throwDetailedException() throws DetailedException { throw new DetailedException("An error occurred", 404); } try { throwDetailedException(); } catch (DetailedException e) { System.out.println(e.getMessage() + " with code " + e.getErrorCode()); }
- Решение:
Использование
throw: Напишите метод, который используетthrowдля выброса исключения.- Решение:java
public void checkCondition(boolean condition) { if (!condition) { throw new IllegalStateException("Condition not met"); } } - Входные данные:java
checkCondition(false); // вызовет исключение
- Решение:
Обработка собственных исключений: Напишите метод, который вызывает свое собственное исключение.
- Решение:java
public void customExceptionDemo() throws CustomException { throw new CustomException("Custom exception thrown"); } - Входные данные:java
try { customExceptionDemo(); } catch (CustomException e) { System.out.println(e.getMessage()); }
- Решение:
Создание исключения с параметрами: Создайте класс исключения с параметрами и используйте его.
- Решение:java
class ValueOutOfRangeException extends Exception { private int value; public ValueOutOfRangeException(String message, int value) { super(message); this.value = value; } public int getValue() { return value; } } - Входные данные:java
public void validateValue(int value) throws ValueOutOfRangeException { if (value < 0 || value > 100) { throw new ValueOutOfRangeException("Value out of range", value); } } try { validateValue(150); // вызовет исключение } catch (ValueOutOfRangeException e) { System.out.println(e.getMessage() + ": " + e.getValue()); }
- Решение:
СОЗДАНИЕ СВОИХ КЛАССОВ ИСКЛЮЧЕНИЙ
Базовые задачи:
Простое пользовательское исключение: Создайте свой класс исключений.
- Решение:java
class MyException extends Exception { public MyException(String message) { super(message); } } - Входные данные:java
public void throwMyException() throws MyException { throw new MyException("This is my custom exception"); } try { throwMyException(); } catch (MyException e) { System.out.println(e.getMessage()); }
- Решение:
Пользовательское исключение с параметрами: Создайте класс с дополнительными параметрами.
- Решение:java
class DetailedMyException extends Exception { private int errorCode; public DetailedMyException(String message, int errorCode) { super(message); this.errorCode = errorCode; } public int getErrorCode() { return errorCode; } } - Входные данные:java
public void throwDetailedMyException() throws DetailedMyException { throw new DetailedMyException("Detailed error", 101); } try { throwDetailedMyException(); } catch (DetailedMyException e) { System.out.println(e.getMessage() + " with code " + e.getErrorCode()); }
- Решение:
Использование пользовательского исключения в методе: Напишите метод, который выбрасывает ваше исключение.
- Решение:java
public void validate(int value) throws MyException { if (value < 0) { throw new MyException("Value must be non-negative"); } } - Входные данные:java
try { validate(-5); // вызовет исключение } catch (MyException e) { System.out.println(e.getMessage()); }
- Решение:
Создание иерархии пользовательских исключений: Создайте родительский и дочерний классы исключений.
- Решение:java
class BaseException extends Exception { public BaseException(String message) { super(message); } } class ChildException extends BaseException { public ChildException(String message) { super(message); } } - Входные данные:java
public void throwChildException() throws ChildException { throw new ChildException("This is a child exception"); } try { throwChildException(); } catch (ChildException e) { System.out.println(e.getMessage()); }
- Решение:
Кастомизация метода исключения: Создайте метод, который выбрасывает ваше пользовательское исключение.
- Решение:java
public void process() throws MyException { throw new MyException("Error during processing"); } - Входные данные:java
try { process(); } catch (MyException e) { System.out.println(e.getMessage()); }
- Решение:
Сложные задачи:
Создание исключения с дополнительной информацией: Создайте класс с параметрами и реализуйте его использование.
- Решение:java
class InvalidUserInputException extends Exception { private String userInput; public InvalidUserInputException(String message, String userInput) { super(message); this.userInput = userInput; } public String getUserInput() { return userInput; } } - Входные данные:java
public void validateInput(String input) throws InvalidUserInputException { if (input == null || input.isEmpty()) { throw new InvalidUserInputException("Input cannot be null or empty", input); } } try { validateInput(""); // вызовет исключение } catch (InvalidUserInputException e) { System.out.println(e.getMessage() + ": " + e.getUserInput()); }
- Решение:
Обработка пользовательского исключения: Создайте метод, который вызывает и обрабатывает пользовательское исключение.
- Решение:java
public void callInvalidInput() { try { validateInput(null); // вызовет исключение } catch (InvalidUserInputException e) { System.out.println("Caught: " + e.getMessage()); } } - Входные данные:java
callInvalidInput();
- Решение:
Создание нескольких классов пользовательских исключений: Создайте несколько классов исключений с разными параметрами.
- Решение:java
class DataNotFoundException extends Exception { public DataNotFoundException(String message) { super(message); } } class OperationFailedException extends Exception { public OperationFailedException(String message) { super(message); } } - Входные данные:java
public void performOperation() throws DataNotFoundException, OperationFailedException { // Логика, которая может выбрасывать исключения throw new DataNotFoundException("Data not found"); } try { performOperation(); } catch (DataNotFoundException | OperationFailedException e) { System.out.println(e.getMessage()); }
- Решение:
Кастомизация метода выброса: Создайте метод, который выбрасывает исключение с параметрами.
- Решение:java
public void processWithCustomException() throws InvalidUserInputException { throw new InvalidUserInputException("Invalid input provided", "undefined"); } - Входные данные:java
try { processWithCustomException(); } catch (InvalidUserInputException e) { System.out.println(e.getMessage() + " for input: " + e.getUserInput()); }
- Решение:
Работа с пользовательскими исключениями: Напишите метод, который генерирует пользовательское исключение на основе условий.
- Решение:java
public void checkCondition(boolean condition) throws InvalidUserInputException { if (!condition) { throw new InvalidUserInputException("Condition not met", "false"); } } - Входные данные:java
try { checkCondition(false); // вызовет исключение } catch (InvalidUserInputException e) { System.out.println(e.getMessage() + ": " + e.getUserInput()); }
- Решение:
ТИПЫ КОЛЛЕКЦИЙ. ИНТЕРФЕЙС COLLECTION
Базовые задачи:
Создание и инициализация коллекции: Создайте коллекцию типа
Collectionи добавьте элементы.- Решение:java
Collection<String> collection = new ArrayList<>(); collection.add("Apple"); collection.add("Banana"); - Входные данные:java
System.out.println(collection);
- Решение:
Проверка наличия элемента: Проверьте, содержится ли элемент в коллекции.
- Решение:java
boolean containsApple = collection.contains("Apple"); - Входные данные:java
System.out.println("Contains Apple: " + containsApple);
- Решение:
Удаление элемента: Удалите элемент из коллекции.
- Решение:java
collection.remove("Banana"); - Входные данные:java
System.out.println(collection);
- Решение:
Итерация по элементам: Используйте цикл
for-eachдля итерации по элементам коллекции.- Решение:java
for (String fruit : collection) { System.out.println(fruit); } - Входные данные:java
// Будет напечатано каждое значение из коллекции
- Решение:
Получение размера коллекции: Выведите размер коллекции.
- Решение:java
int size = collection.size(); - Входные данные:java
System.out.println("Size: " + size);
- Решение:
Сложные задачи:
Объединение двух коллекций: Создайте метод, который объединяет две коллекции.
- Решение:java
public Collection<String> mergeCollections(Collection<String> c1, Collection<String> c2) { c1.addAll(c2); return c1; } - Входные данные:java
Collection<String> c1 = new ArrayList<>(Arrays.asList("Apple", "Banana")); Collection<String> c2 = new ArrayList<>(Arrays.asList("Orange", "Grapes")); System.out.println(mergeCollections(c1, c2));
- Решение:
Перекрестное сравнение коллекций: Напишите метод, который находит общие элементы двух коллекций.
- Решение:java
public Collection<String> commonElements(Collection<String> c1, Collection<String> c2) { Collection<String> common = new ArrayList<>(c1); common.retainAll(c2); return common; } - Входные данные:java
Collection<String> common = commonElements(c1, c2); System.out.println(common); // Выведет общие элементы
- Решение:
Создание коллекции из массива: Напишите метод, который принимает массив и возвращает коллекцию.
- Решение:java
public Collection<String> arrayToCollection(String[] array) { return new ArrayList<>(Arrays.asList(array)); } - Входные данные:java
String[] fruits = {"Apple", "Banana", "Cherry"}; Collection<String> collection = arrayToCollection(fruits); System.out.println(collection);
- Решение:
Фильтрация коллекции: Создайте метод, который фильтрует элементы коллекции по определенному критерию.
- Решение:java
public Collection<String> filterCollection(Collection<String> collection, String criteria) { Collection<String> filtered = new ArrayList<>(); for (String item : collection) { if (item.contains(criteria)) { filtered.add(item); } } return filtered; } - Входные данные:java
Collection<String> filtered = filterCollection(collection, "a"); System.out.println(filtered); // Выведет элементы с "a"
- Решение:
Создание множества на основе коллекции: Напишите метод, который преобразует коллекцию в множество.
- Решение:java
public Set<String> collectionToSet(Collection<String> collection) { return new HashSet<>(collection); } - Входные данные:java
Set<String> set = collectionToSet(collection); System.out.println(set);
- Решение:
КЛАСС ARRAYLIST И ИНТЕРФЕЙС LIST
Базовые задачи:
Создание
ArrayList: СоздайтеArrayListи добавьте элементы.- Решение:java
List<String> list = new ArrayList<>(); list.add("Apple"); list.add("Banana"); - Входные данные:java
System.out.println(list);
- Решение:
Получение элемента по индексу: Получите элемент по индексу.
- Решение:java
String fruit = list.get(0); - Входные данные:java
System.out.println("First element: " + fruit);
- Решение:
Изменение элемента: Измените элемент в списке.
- Решение:java
list.set(1, "Cherry"); - Входные данные:java
System.out.println(list);
- Решение:
Удаление элемента: Удалите элемент по индексу.
- Решение:java
list.remove(0); - Входные данные:java
System.out.println(list);
- Решение:
Проверка наличия элемента: Проверьте наличие элемента в
ArrayList.- Решение:java
boolean exists = list.contains("Cherry"); - Входные данные:java
System.out.println("Contains Cherry: " + exists);
- Решение:
Сложные задачи:
Сортировка списка: Отсортируйте
ArrayListв алфавитном порядке.- Решение:java
Collections.sort(list); - Входные данные:java
System.out.println(list);
- Решение:
Копирование списка: Создайте метод, который копирует один
ArrayListв другой.- Решение:java
public List<String> copyList(List<String> original) { return new ArrayList<>(original); } - Входные данные:java
List<String> copiedList = copyList(list); System.out.println(copiedList);
- Решение:
Объединение двух списков: Создайте метод, который объединяет два списка.
- Решение:java
public List<String> mergeLists(List<String> list1, List<String> list2) { List<String> merged = new ArrayList<>(list1); merged.addAll(list2); return merged; } - Входные данные:java
List<String> list2 = new ArrayList<>(Arrays.asList("Grapes", "Peach")); List<String> mergedList = mergeLists(list, list2); System.out.println(mergedList);
- Решение:
Получение подсписка: Получите подсписок из
ArrayList.- Решение:java
public List<String> getSubList(List<String> list, int start, int end) { return list.subList(start, end); } - Входные данные:java
List<String> subList = getSubList(list, 0, 2); System.out.println(subList);
- Решение:
Поиск индекса элемента: Найдите индекс элемента в
ArrayList.- Решение:java
int index = list.indexOf("Cherry"); - Входные данные:java
System.out.println("Index of Cherry: " + index);
- Решение:
ОЧЕРЕДИ И КЛАСС ARRAYDEQUE
Базовые задачи:
Создание
ArrayDeque: Создайте очередь с помощьюArrayDeque.- Решение:java
ArrayDeque<String> queue = new ArrayDeque<>(); queue.add("Apple"); queue.add("Banana"); - Входные данные:java
System.out.println(queue);
- Решение:
Добавление элемента в очередь: Добавьте элемент в очередь.
- Решение:java
queue.offer("Cherry"); - Входные данные:java
System.out.println(queue);
- Решение:
Удаление элемента из очереди: Удалите элемент из очереди.
- Решение:java
String removed = queue.poll(); - Входные данные:java
System.out.println("Removed: " + removed); System.out.println(queue);
- Решение:
Получение элемента без удаления: Получите элемент из очереди без его удаления.
- Решение:java
String head = queue.peek(); - Входные данные:java
System.out.println("Head: " + head);
- Решение:
Проверка пустоты очереди: Проверьте, пуста ли очередь.
- Решение:java
boolean isEmpty = queue.isEmpty(); - Входные данные:java
System.out.println("Is queue empty: " + isEmpty);
- Решение:
Сложные задачи:
Итерация по очереди: Используйте цикл для итерации по элементам очереди.
- Решение:java
for (String item : queue) { System.out.println(item); } - Входные данные:java
// Будет напечатано каждое значение из очереди
- Решение:
Очередь с приоритетом: Создайте очередь с приоритетом и добавьте элементы.
- Решение:java
PriorityQueue<String> priorityQueue = new PriorityQueue<>(); priorityQueue.add("Banana"); priorityQueue.add("Apple"); - Входные данные:java
System.out.println(priorityQueue);
- Решение:
Копирование очереди: Создайте метод для копирования
ArrayDeque.- Решение:java
public ArrayDeque<String> copyDeque(ArrayDeque<String> original) { return new ArrayDeque<>(original); } - Входные данные:java
ArrayDeque<String> copiedQueue = copyDeque(queue); System.out.println(copiedQueue);
- Решение:
Объединение двух очередей: Создайте метод для объединения двух очередей.
- Решение:java
public ArrayDeque<String> mergeQueues(ArrayDeque<String> q1, ArrayDeque<String> q2) { q1.addAll(q2); return q1; } - Входные данные:java
ArrayDeque<String> queue2 = new ArrayDeque<>(Arrays.asList("Grapes", "Peach")); ArrayDeque<String> mergedQueue = mergeQueues(queue, queue2); System.out.println(mergedQueue);
- Решение:
Сортировка очереди: Сортируйте очередь с помощью вспомогательного списка.
- Решение:java
public ArrayDeque<String> sortQueue(ArrayDeque<String> queue) { List<String> list = new ArrayList<>(queue); Collections.sort(list); return new ArrayDeque<>(list); } - Входные данные:java
ArrayDeque<String> sortedQueue = sortQueue(queue); System.out.println(sortedQueue);
- Решение:
КЛАСС LINKEDLIST
Базовые задачи:
Создание
LinkedList: СоздайтеLinkedListи добавьте элементы.- Решение:java
LinkedList<String> linkedList = new LinkedList<>(); linkedList.add("Apple"); linkedList.add("Banana"); - Входные данные:java
System.out.println(linkedList);
- Решение:
Добавление элемента в начало: Добавьте элемент в начало списка.
- Решение:java
linkedList.addFirst("Cherry"); - Входные данные:java
System.out.println(linkedList);
- Решение:
Удаление элемента по индексу: Удалите элемент по индексу.
- Решение:java
linkedList.remove(1); - Входные данные:java
System.out.println(linkedList);
- Решение:
Получение первого и последнего элемента: Получите первый и последний элемент.
- Решение:java
String first = linkedList.getFirst(); String last = linkedList.getLast(); - Входные данные:java
System.out.println("First: " + first); System.out.println("Last: " + last);
- Решение:
Проверка наличия элемента: Проверьте наличие элемента в
LinkedList.- Решение:java
boolean exists = linkedList.contains("Banana"); - Входные данные:java
System.out.println("Contains Banana: " + exists);
- Решение:
Сложные задачи:
Объединение двух списков: Создайте метод, который объединяет два
LinkedList.- Решение:java
public LinkedList<String> mergeLinkedLists(LinkedList<String> l1, LinkedList<String> l2) { l1.addAll(l2); return l1; } - Входные данные:java
LinkedList<String> list2 = new LinkedList<>(Arrays.asList("Grapes", "Peach")); LinkedList<String> mergedList = mergeLinkedLists(linkedList, list2); System.out.println(mergedList);
- Решение:
Удаление дубликатов: Создайте метод, который удаляет дубликаты из
LinkedList.- Решение:java
public LinkedList<String> removeDuplicates(LinkedList<String> list) { Set<String> set = new HashSet<>(list); return new LinkedList<>(set); } - Входные данные:java
linkedList.add("Apple"); // добавим дубликат LinkedList<String> uniqueList = removeDuplicates(linkedList); System.out.println(uniqueList);
- Решение:
Реверс списка: Напишите метод, который реверсирует
LinkedList.- Решение:java
public LinkedList<String> reverseList(LinkedList<String> list) { LinkedList<String> reversed = new LinkedList<>(); for (String item : list) { reversed.addFirst(item); } return reversed; } - Входные данные:java
LinkedList<String> reversedList = reverseList(linkedList); System.out.println(reversedList);
- Решение:
Получение подсписка: Получите подсписок из
LinkedList.- Решение:java
public List<String> getSubList(LinkedList<String> list, int start, int end) { return list.subList(start, end); } - Входные данные:java
List<String> subList = getSubList(linkedList, 0, 2); System.out.println(subList);
- Решение:
Сортировка
LinkedList: ОтсортируйтеLinkedListв алфавитном порядке.- Решение:java
public LinkedList<String> sortList(LinkedList<String> list) { List<String> tempList = new ArrayList<>(list); Collections.sort(tempList); return new LinkedList<>(tempList); } - Входные данные:java
LinkedList<String> sortedList = sortList(linkedList); System.out.println(sortedList);
- Решение:
ИНТЕРФЕЙС SET И КЛАСС HASHSET
Базовые задачи:
Создание
HashSet: Создайте множество с помощьюHashSet.- Решение:java
Set<String> set = new HashSet<>(); set.add("Apple"); set.add("Banana"); - Входные данные:java
System.out.println(set);
- Решение:
Проверка наличия элемента: Проверьте наличие элемента в
HashSet.- Решение:java
boolean exists = set.contains("Banana"); - Входные данные:java
System.out.println("Contains Banana: " + exists);
- Решение:
Удаление элемента: Удалите элемент из множества.
- Решение:java
set.remove("Apple"); - Входные данные:java
System.out.println(set);
- Решение:
Получение размера множества: Выведите размер
HashSet.- Решение:java
int size = set.size(); - Входные данные:java
System.out.println("Size: " + size);
- Решение:
Итерация по элементам множества: Используйте цикл для итерации по элементам
HashSet.- Решение:java
for (String fruit : set) { System.out.println(fruit); } - Входные данные:java
// Будет напечатано каждое значение из множества
- Решение:
Сложные задачи:
Объединение двух множеств: Создайте метод, который объединяет два множества.
- Решение:java
public Set<String> mergeSets(Set<String> set1, Set<String> set2) { Set<String> merged = new HashSet<>(set1); merged.addAll(set2); return merged; } - Входные данные:java
Set<String> set2 = new HashSet<>(Arrays.asList("Cherry", "Banana")); Set<String> mergedSet = mergeSets(set, set2); System.out.println(mergedSet);
- Решение:
Пересечение двух множеств: Создайте метод, который находит пересечение двух множеств.
- Решение:java
public Set<String> intersectSets(Set<String> set1, Set<String> set2) { Set<String> intersection = new HashSet<>(set1); intersection.retainAll(set2); return intersection; } - Входные данные:java
Set<String> intersection = intersectSets(set, set2); System.out.println(intersection);
- Решение:
Удаление дубликатов из списка с использованием множества: Напишите метод, который удаляет дубликаты из списка, используя
HashSet.- Решение:java
public Set<String> removeDuplicates(List<String> list) { return new HashSet<>(list); } - Входные данные:java
List<String> fruits = Arrays.asList("Apple", "Banana", "Apple"); Set<String> uniqueFruits = removeDuplicates(fruits); System.out.println(uniqueFruits);
- Решение:
Сравнение множеств: Создайте метод, который проверяет, равны ли два множества.
- Решение:java
public boolean areSetsEqual(Set<String> set1, Set<String> set2) { return set1.equals(set2); } - Входные данные:java
boolean equal = areSetsEqual(set, set2); System.out.println("Sets are equal: " + equal);
- Решение:
Сортировка множества: Создайте метод, который сортирует элементы множества и возвращает
List.- Решение:java
public List<String> sortSet(Set<String> set) { List<String> sortedList = new ArrayList<>(set); Collections.sort(sortedList); return sortedList; } - Входные данные:java
List<String> sortedSet = sortSet(set); System.out.println(sortedSet);
- Решение:
SORTEDSET, NAVIGABLESET, TREESET
Базовые задачи:
Создание
TreeSet: СоздайтеTreeSetи добавьте элементы.- Решение:java
NavigableSet<String> treeSet = new TreeSet<>(); treeSet.add("Banana"); treeSet.add("Apple"); - Входные данные:java
System.out.println(treeSet);
- Решение:
Получение первого и последнего элемента: Получите первый и последний элемент из
TreeSet.- Решение:java
String first = treeSet.first(); String last = treeSet.last(); - Входные данные:java
System.out.println("First: " + first); System.out.println("Last: " + last);
- Решение:
Удаление первого и последнего элемента: Удалите первый и последний элемент из
TreeSet.- Решение:java
treeSet.pollFirst(); treeSet.pollLast(); - Входные данные:java
System.out.println(treeSet);
- Решение:
Получение элемента по навигации: Получите элемент, который меньше или равен заданному значению.
- Решение:java
String lower = treeSet.lower("Banana"); - Входные данные:java
System.out.println("Lower than Banana: " + lower);
- Решение:
Итерация по элементам
TreeSet: Используйте цикл для итерации по элементамTreeSet.- Решение:java
for (String fruit : treeSet) { System.out.println(fruit); } - Входные данные:java
// Будет напечатано каждое значение из `TreeSet`
- Решение:
Сложные задачи:
Фильтрация
TreeSet: Создайте метод, который фильтрует элементы вTreeSet.- Решение:java
public NavigableSet<String> filterTreeSet(NavigableSet<String> set, String criteria) { return set.subSet(criteria, true, set.last(), true); } - Входные данные:java
NavigableSet<String> filteredSet = filterTreeSet(treeSet, "Apple"); System.out.println(filteredSet);
- Решение:
Объединение двух
NavigableSet: Создайте метод, который объединяет дваNavigableSet.- Решение:java
public NavigableSet<String> mergeNavigableSets(NavigableSet<String> set1, NavigableSet<String> set2) { set1.addAll(set2); return set1; } - Входные данные:java
NavigableSet<String> treeSet2 = new TreeSet<>(Arrays.asList("Cherry", "Grapes")); NavigableSet<String> mergedSet = mergeNavigableSets(treeSet, treeSet2); System.out.println(mergedSet);
- Решение:
Сравнение двух
NavigableSet: Создайте метод, который сравнивает дваNavigableSet.- Решение:java
public boolean areNavigableSetsEqual(NavigableSet<String> set1, NavigableSet<String> set2) { return set1.equals(set2); } - Входные данные:java
boolean equal = areNavigableSetsEqual(treeSet, treeSet2); System.out.println("Sets are equal: " + equal);
- Решение:
Получение подмножества: Получите подмножество из
TreeSet.- Решение:java
public NavigableSet<String> getSubSet(NavigableSet<String> set, String fromElement, String toElement) { return set.subSet(fromElement, true, toElement, true); } - Входные данные:java
NavigableSet<String> subSet = getSubSet(treeSet, "Apple", "Cherry"); System.out.println(subSet);
- Решение:
Сортировка
TreeSet: Создайте метод, который сортирует элементы вTreeSet.- Решение:java
public NavigableSet<String> sortTreeSet(NavigableSet<String> set) { List<String> sortedList = new ArrayList<>(set); Collections.sort(sortedList); return new TreeSet<>(sortedList); } - Входные данные:java
NavigableSet<String> sortedTreeSet = sortTreeSet(treeSet); System.out.println(sortedTreeSet);
- Решение:
ИНТЕРФЕЙСЫ COMPARABLE И COMPARATOR. СОРТИРОВКА
Базовые задачи:
Создание класса с
Comparable: Создайте классFruitс интерфейсомComparable.- Решение:java
public class Fruit implements Comparable<Fruit> { String name; public Fruit(String name) { this.name = name; } @Override public int compareTo(Fruit other) { return this.name.compareTo(other.name); } } - Входные данные:java
Fruit apple = new Fruit("Apple"); Fruit banana = new Fruit("Banana"); System.out.println(apple.compareTo(banana));
- Решение:
Создание класса с
Comparator: Создайте классFruitComparator, который сравнивает по длине имени.- Решение:java
public class FruitComparator implements Comparator<Fruit> { @Override public int compare(Fruit f1, Fruit f2) { return Integer.compare(f1.name.length(), f2.name.length()); } } - Входные данные:java
FruitComparator comparator = new FruitComparator(); System.out.println(comparator.compare(apple, banana));
- Решение:
Сортировка списка с
Comparable: Создайте списокFruitи отсортируйте его.- Решение:java
List<Fruit> fruits = Arrays.asList(new Fruit("Banana"), new Fruit("Apple")); Collections.sort(fruits); - Входные данные:java
System.out.println(fruits);
- Решение:
Сортировка списка с
Comparator: Создайте списокFruitи отсортируйте его с использованиемFruitComparator.- Решение:java
Collections.sort(fruits, new FruitComparator()); - Входные данные:java
System.out.println(fruits);
- Решение:
Сортировка массива: Отсортируйте массив строк по длине.
- Решение:java
String[] fruitsArray = {"Banana", "Apple", "Cherry"}; Arrays.sort(fruitsArray, Comparator.comparingInt(String::length)); - Входные данные:java
System.out.println(Arrays.toString(fruitsArray));
- Решение:
Сложные задачи:
Компаратор по нескольким критериям: Создайте компаратор, который сначала сортирует по длине, затем по алфавиту.
- Решение:java
public class MultiCriteriaComparator implements Comparator<Fruit> { @Override public int compare(Fruit f1, Fruit f2) { int lengthComparison = Integer.compare(f1.name.length(), f2.name.length()); return lengthComparison != 0 ? lengthComparison : f1.name.compareTo(f2.name); } } - Входные данные:java
Collections.sort(fruits, new MultiCriteriaComparator());
- Решение:
Использование лямбда-выражений для сортировки: Отсортируйте список с использованием лямбда-выражений.
- Решение:java
Collections.sort(fruits, (f1, f2) -> f1.name.compareTo(f2.name)); - Входные данные:java
System.out.println(fruits);
- Решение:
Создание метода для сортировки по имени: Создайте метод, который сортирует список по имени.
- Решение:java
public static void sortByName(List<Fruit> fruits) { Collections.sort(fruits, Comparator.comparing(f -> f.name)); } - Входные данные:java
sortByName(fruits);
- Решение:
Сортировка в обратном порядке: Создайте метод, который сортирует по имени в обратном порядке.
- Решение:java
public static void sortByNameReverse(List<Fruit> fruits) { Collections.sort(fruits, Comparator.comparing(Fruit::name).reversed()); } - Входные данные:java
sortByNameReverse(fruits);
- Решение:
Генерация компаратора на лету: Используйте метод
Comparator.naturalOrder()для сортировки.- Решение:java
Collections.sort(fruits, Comparator.naturalOrder()); - Входные данные:java
System.out.println(fruits);
- Решение:
ПОТОКИ ВВОДА-ВЫВОДА
Базовые задачи:
Создание объекта
File: Создайте объектFileи проверьте, существует ли указанный файл.- Решение:java
File file = new File("test.txt"); boolean exists = file.exists(); System.out.println("File exists: " + exists); - Входные данные:java
// Путь к файлу: "test.txt"
- Решение:
Получение информации о файле: Выведите размер файла и его абсолютный путь.
- Решение:java
System.out.println("Size: " + file.length() + " bytes"); System.out.println("Absolute Path: " + file.getAbsolutePath()); - Входные данные:java
// Путь к файлу: "test.txt"
- Решение:
Создание нового файла: Создайте новый файл и выведите сообщение об успехе.
- Решение:java
boolean created = file.createNewFile(); System.out.println("File created: " + created); - Входные данные:java
// Путь к файлу: "test.txt"
- Решение:
Удаление файла: Удалите файл и выведите сообщение об успехе.
- Решение:java
boolean deleted = file.delete(); System.out.println("File deleted: " + deleted); - Входные данные:java
// Путь к файлу: "test.txt"
- Решение:
Перемещение файла: Переместите файл в другой каталог.
- Решение:java
File newFile = new File("newDir/test.txt"); boolean moved = file.renameTo(newFile); System.out.println("File moved: " + moved); - Входные данные:java
// Путь к файлу: "test.txt" // Новый каталог: "newDir/"
- Решение:
ЧТЕНИЕ И ЗАПИСЬ ФАЙЛОВ. FILEINPUTSTREAM И FILEOUTPUTSTREAM
Базовые задачи:
Запись байтов в файл: Используйте
FileOutputStreamдля записи байтов в файл.- Решение:java
FileOutputStream fos = new FileOutputStream("output.txt"); fos.write("Hello, World!".getBytes()); fos.close(); - Входные данные:java
// Записываем строку: "Hello, World!"
- Решение:
Чтение байтов из файла: Используйте
FileInputStreamдля чтения байтов из файла.- Решение:java
FileInputStream fis = new FileInputStream("output.txt"); int data; while ((data = fis.read()) != -1) { System.out.print((char) data); } fis.close(); - Входные данные:java
// Читаем из файла: "output.txt"
- Решение:
Запись массива байтов в файл: Используйте
FileOutputStreamдля записи массива байтов в файл.- Решение:java
byte[] data = {65, 66, 67}; FileOutputStream fos = new FileOutputStream("outputBytes.txt"); fos.write(data); fos.close(); - Входные данные:java
// Записываем массив: {65, 66, 67}
- Решение:
Чтение из файла с помощью
FileInputStream: Прочитайте данные и выведите их на экран.- Решение:java
FileInputStream fis = new FileInputStream("outputBytes.txt"); int byteData; while ((byteData = fis.read()) != -1) { System.out.print(byteData + " "); } fis.close(); - Входные данные:java
// Читаем из файла: "outputBytes.txt"
- Решение:
Проверка существования файла перед чтением: Проверьте, существует ли файл перед его чтением.
- Решение:java
File file = new File("output.txt"); if (file.exists()) { FileInputStream fis = new FileInputStream(file); // Чтение данных } else { System.out.println("File does not exist."); } - Входные данные:java
// Проверка файла: "output.txt"
- Решение:
Закрытие потоков
Базовые задачи:
Правильное закрытие
FileOutputStream: Используйтеtry-with-resourcesдля автоматического закрытия потока.- Решение:java
try (FileOutputStream fos = new FileOutputStream("output.txt")) { fos.write("Hello".getBytes()); } - Входные данные:java
// Записываем строку: "Hello"
- Решение:
Закрытие
FileInputStream: Используйтеtry-with-resourcesдля закрытия входного потока.- Решение:java
try (FileInputStream fis = new FileInputStream("output.txt")) { int data; while ((data = fis.read()) != -1) { System.out.print((char) data); } } - Входные данные:java
// Читаем из файла: "output.txt"
- Решение:
Закрытие нескольких потоков: Используйте
try-with-resourcesдля нескольких потоков.- Решение:java
try (FileOutputStream fos = new FileOutputStream("output.txt"); FileInputStream fis = new FileInputStream("output.txt")) { fos.write("Data".getBytes()); } - Входные данные:java
// Записываем строку: "Data"
- Решение:
Закрытие
BufferedInputStream: Используйтеtry-with-resourcesдляBufferedInputStream.- Решение:java
try (BufferedInputStream bis = new BufferedInputStream(new FileInputStream("output.txt"))) { int data; while ((data = bis.read()) != -1) { System.out.print((char) data); } } - Входные данные:java
// Читаем из файла: "output.txt"
- Решение:
Закрытие
PrintWriter: Используйтеtry-with-resourcesдляPrintWriter.- Решение:java
try (PrintWriter pw = new PrintWriter(new FileOutputStream("output.txt"))) { pw.println("Hello, World!"); } - Входные данные:java
// Записываем строку: "Hello, World!"
- Решение:
КЛАССЫ BYTEARRAYINPUTSTREAM И BYTEARRAYOUTPUTSTREAM
Базовые задачи:
Создание
ByteArrayOutputStream: Запишите данные вByteArrayOutputStream.- Решение:java
ByteArrayOutputStream baos = new ByteArrayOutputStream(); baos.write("Hello".getBytes()); byte[] data = baos.toByteArray(); System.out.println(new String(data)); - Входные данные:java
// Записываем строку: "Hello"
- Решение:
Чтение из
ByteArrayInputStream: Читайте данные изByteArrayInputStream.- Решение:java
ByteArrayInputStream bais = new ByteArrayInputStream(data); int byteData; while ((byteData = bais.read()) != -1) { System.out.print((char) byteData); } - Входные данные:java
// Читаем из массива данных
- Решение:
Запись нескольких строк: Используйте
ByteArrayOutputStreamдля записи нескольких строк.- Решение:java
ByteArrayOutputStream baos = new ByteArrayOutputStream(); baos.write("Line 1\n".getBytes()); baos.write("Line 2\n".getBytes()); byte[] data = baos.toByteArray(); System.out.print(new String(data)); - Входные данные:java
// Записываем строки: "Line 1" и "Line 2"
- Решение:
Чтение строк из массива байтов: Прочитайте данные, записанные в
ByteArrayOutputStream.- Решение:java
ByteArrayInputStream bais = new ByteArrayInputStream(data); BufferedReader reader = new BufferedReader(new InputStreamReader(bais)); String line; while ((line = reader.readLine()) != null) { System.out.println(line); } - Входные данные:java
// Читаем из массива данных
- Решение:
Использование
ByteArrayOutputStreamдля форматированного вывода: ИспользуйтеByteArrayOutputStreamдля записи форматированных данных.- Решение:java
ByteArrayOutputStream baos = new ByteArrayOutputStream(); PrintWriter writer = new PrintWriter(baos); writer.printf("Value: %d%n", 42); writer.flush(); System.out.print(baos.toString()); - Входные данные:java
// Форматируем строку с числом: 42
- Решение:
БУФЕРИЗОВАННЫЕ ПОТОКИ BUFFEREDINPUTSTREAM И BUFFEREDOUTPUTSTREAM
Базовые задачи:
Запись с использованием
BufferedOutputStream: Запишите данные с использованиемBufferedOutputStream.- Решение:java
try (BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream("bufferedOutput.txt"))) { bos.write("Buffered Output".getBytes()); } - Входные данные:java
// Записываем строку: "Buffered Output"
- Решение:
Чтение с использованием
BufferedInputStream: Прочитайте данные с использованиемBufferedInputStream.- Решение:java
try (BufferedInputStream bis = new BufferedInputStream(new FileInputStream("bufferedOutput.txt"))) { int data; while ((data = bis.read()) != -1) { System.out.print((char) data); } } - Входные данные:java
// Читаем из файла: "bufferedOutput.txt"
- Решение:
Проверка производительности: Сравните производительность записи с
BufferedOutputStreamи без него.- Решение:java
long start = System.currentTimeMillis(); FileOutputStream fos = new FileOutputStream("output.txt"); for (int i = 0; i < 10000; i++) { fos.write("Test\n".getBytes()); } fos.close(); long end = System.currentTimeMillis(); System.out.println("Time without buffer: " + (end - start) + " ms"); start = System.currentTimeMillis(); BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream("bufferedOutput.txt")); for (int i = 0; i < 10000; i++) { bos.write("Test\n".getBytes()); } bos.close(); end = System.currentTimeMillis(); System.out.println("Time with buffer: " + (end - start) + " ms"); - Входные данные:java
// Записываем 10000 строк "Test"
- Решение:
Копирование файла: Используйте
BufferedInputStreamиBufferedOutputStreamдля копирования файла.- Решение:java
try (BufferedInputStream bis = new BufferedInputStream(new FileInputStream("source.txt")); BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream("copy.txt"))) { byte[] buffer = new byte[1024]; int bytesRead; while ((bytesRead = bis.read(buffer)) != -1) { bos.write(buffer, 0, bytesRead); } } - Входные данные:java
// Копируем файл: "source.txt" в "copy.txt"
- Решение:
Чтение строк с использованием
BufferedReader: ИспользуйтеBufferedReaderдля чтения строк.- Решение:java
try (BufferedReader br = new BufferedReader(new FileReader("bufferedOutput.txt"))) { String line; while ((line = br.readLine()) != null) { System.out.println(line); } } - Входные данные:java
// Читаем из файла: "bufferedOutput.txt"
- Решение:
ФОРМАТИРУЕМЫЙ ВЫВОД. PRINTSTREAM И PRINTWRITER
Базовые задачи:
Запись с использованием
PrintWriter: ИспользуйтеPrintWriterдля записи данных в файл.- Решение:java
try (PrintWriter pw = new PrintWriter(new FileOutputStream("printWriterOutput.txt"))) { pw.println("Hello, PrintWriter!"); } - Входные данные:java
// Записываем строку: "Hello, PrintWriter!"
- Решение:
Форматирование данных с
PrintWriter: Запишите отформатированную строку в файл.- Решение:java
try (PrintWriter pw = new PrintWriter(new FileOutputStream("formattedOutput.txt"))) { pw.printf("Integer: %d, Float: %.2f%n", 42, 3.14); } - Входные данные:java
// Форматируем строку: "Integer: 42, Float: 3.14"
- Решение:
Использование
PrintStream: Запишите данные с использованиемPrintStream.- Решение:java
try (PrintStream ps = new PrintStream(new FileOutputStream("printStreamOutput.txt"))) { ps.println("Hello, PrintStream!"); } - Входные данные:java
// Записываем строку: "Hello, PrintStream!"
- Решение:
Запись массива с использованием
PrintWriter: Запишите массив строк в файл.- Решение:java
try (PrintWriter pw = new PrintWriter(new FileOutputStream("arrayOutput.txt"))) { String[] lines = {"Line 1", "Line 2", "Line 3"}; for (String line : lines) { pw.println(line); } } - Входные данные:java
// Записываем массив строк: {"Line 1", "Line 2", "Line 3"}
- Решение:
Форматирование вывода с использованием
PrintWriter: ИспользуйтеPrintWriterдля записи отформатированных данных.- Решение:java
try (PrintWriter pw = new PrintWriter(new FileOutputStream("formattedPrintOutput.txt"))) { for (int i = 1; i <= 5; i++) { pw.printf("Line %d: %s%n", i, "Some data"); } } - Входные данные:java
// Записываем 5 строк с форматом
- Решение:
КЛАССЫ DATAOUTPUTSTREAM И DATAINPUTSTREAM
Базовые задачи:
Запись данных с использованием
DataOutputStream: Запишите различные типы данных в файл.- Решение:java
try (DataOutputStream dos = new DataOutputStream(new FileOutputStream("dataOutput.dat"))) { dos.writeInt(42); dos.writeDouble(3.14); dos.writeUTF("Hello"); } - Входные данные:java
// Записываем данные: 42, 3.14, "Hello"
- Решение:
Чтение данных с использованием
DataInputStream: Прочитайте данные, записанные в предыдущем шаге.- Решение:java
try (DataInputStream dis = new DataInputStream(new FileInputStream("dataOutput.dat"))) { int intValue = dis.readInt(); double doubleValue = dis.readDouble(); String stringValue = dis.readUTF(); System.out.println(intValue + ", " + doubleValue + ", " + stringValue); } - Входные данные:java
// Читаем из файла: "dataOutput.dat"
- Решение:
Запись массива целых чисел: Запишите массив целых чисел в файл.
- Решение:java
try (DataOutputStream dos = new DataOutputStream(new FileOutputStream("intArray.dat"))) { int[] numbers = {1, 2, 3, 4, 5}; for (int number : numbers) { dos.writeInt(number); } } - Входные данные:java
// Записываем массив: {1, 2, 3, 4, 5}
- Решение:
Чтение массива целых чисел: Прочитайте массив целых чисел из файла.
- Решение:java
try (DataInputStream dis = new DataInputStream(new FileInputStream("intArray.dat"))) { for (int i = 0; i < 5; i++) { System.out.print(dis.readInt() + " "); } } - Входные данные:java
// Читаем из файла: "intArray.dat"
- Решение:
Запись различных типов данных: Запишите разные типы данных в одном файле.
- Решение:java
try (DataOutputStream dos = new DataOutputStream(new FileOutputStream("mixedData.dat"))) { dos.writeInt(100); dos.writeDouble(3.14159); dos.writeBoolean(true); } - Входные данные:java
// Записываем данные: 100, 3.14159, true
- Решение:
ЧТЕНИЕ И ЗАПИСЬ ТЕКСТОВЫХ ФАЙЛОВ
Базовые задачи:
Запись текста в файл: Запишите текст в файл с использованием
FileWriter.- Решение:java
try (FileWriter fw = new FileWriter("textFile.txt")) { fw.write("Hello, World!"); } - Входные данные:java
// Записываем строку: "Hello, World!"
- Решение:
Чтение текста из файла: Прочитайте текст из файла с использованием
FileReader.- Решение:java
try (FileReader fr = new FileReader("textFile.txt")) { int data; while ((data = fr.read()) != -1) { System.out.print((char) data); } } - Входные данные:java
// Читаем из файла: "textFile.txt"
- Решение:
Запись нескольких строк в файл: Запишите несколько строк в файл.
- Решение:java
try (BufferedWriter bw = new BufferedWriter(new FileWriter("multipleLines.txt"))) { bw.write("First Line"); bw.newLine(); bw.write("Second Line"); } - Входные данные:java
// Записываем строки: "First Line", "Second Line"
- Решение:
Чтение строк из файла: Прочитайте строки из файла и выведите их на экран.
- Решение:java
try (BufferedReader br = new BufferedReader(new FileReader("multipleLines.txt"))) { String line; while ((line = br.readLine()) != null) { System.out.println(line); } } - Входные данные:java
// Читаем из файла: "multipleLines.txt"
- Решение:
Запись и чтение текста с использованием
PrintWriter: ИспользуйтеPrintWriterдля записи и чтения текста.- Решение:java
try (PrintWriter pw = new PrintWriter(new FileOutputStream("printWriterText.txt"))) { pw.println("Hello, PrintWriter!"); } try (BufferedReader br = new BufferedReader(new FileReader("printWriterText.txt"))) { String line; while ((line = br.readLine()) != null) { System.out.println(line); } } - Входные данные:java
// Записываем и читаем: "Hello, PrintWriter!"
- Решение:
БУФЕРИЗАЦИЯ СИМВОЛЬНЫХ ПОТОКОВ. BUFFEREDREADER И BUFFEREDWRITER
Базовые задачи:
Запись с использованием
BufferedWriter: Запишите текст в файл с использованиемBufferedWriter.- Решение:java
try (BufferedWriter bw = new BufferedWriter(new FileWriter("bufferedText.txt"))) { bw.write("Buffered Writer Example"); } - Входные данные:java
// Записываем строку: "Buffered Writer Example"
- Решение:
Чтение с использованием
BufferedReader: Прочитайте текст из файла с использованиемBufferedReader.- Решение:java
try (BufferedReader br = new BufferedReader(new FileReader("bufferedText.txt"))) { String line; while ((line = br.readLine()) != null) { System.out.println(line); } } - Входные данные:java
// Читаем из файла: "bufferedText.txt"
- Решение:
Копирование файла с использованием буферизации: Используйте
BufferedReaderиBufferedWriterдля копирования файла.- Решение:java
try (BufferedReader br = new BufferedReader(new FileReader("source.txt")); BufferedWriter bw = new BufferedWriter(new FileWriter("copyBuffered.txt"))) { String line; while ((line = br.readLine()) != null) { bw.write(line); bw.newLine(); } } - Входные данные:java
// Копируем файл: "source.txt" в "copyBuffered.txt"
- Решение:
Запись массива строк с использованием
BufferedWriter: Запишите массив строк в файл.- Решение:java
String[] lines = {"Line 1", "Line 2", "Line 3"}; try (BufferedWriter bw = new BufferedWriter(new FileWriter("arrayBuffered.txt"))) { for (String line : lines) { bw.write(line); bw.newLine(); } } - Входные данные:java
// Записываем массив строк: {"Line 1", "Line 2", "Line 3"}
- Решение:
Чтение и запись с использованием буферизации: Прочитайте данные из одного файла и запишите их в другой.
- Решение:java
try (BufferedReader br = new BufferedReader(new FileReader("input.txt")); BufferedWriter bw = new BufferedWriter(new FileWriter("output.txt"))) { String line; while ((line = br.readLine()) != null) { bw.write(line); bw.newLine(); } } - Входные данные:java
// Читаем из файла: "input.txt" и записываем в "output.txt"
- Решение:
СЕРИАЛИЗАЦИЯ ОБЪЕКТОВ
Базовые задачи:
Сериализация объекта: Сериализуйте объект и запишите его в файл.
- Решение:java
import java.io.*; class Person implements Serializable { String name; int age; Person(String name, int age) { this.name = name; this.age = age; } } Person person = new Person("Alice", 30); try (ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("person.ser"))) { oos.writeObject(person); } - Входные данные:java
// Создаем объект Person с данными: "Alice", 30
- Решение:
Десериализация объекта: Десериализуйте объект из файла и выведите его свойства.
- Решение:java
try (ObjectInputStream ois = new ObjectInputStream(new FileInputStream("person.ser"))) { Person deserializedPerson = (Person) ois.readObject(); System.out.println("Name: " + deserializedPerson.name + ", Age: " + deserializedPerson.age); } - Входные данные:java
// Читаем из файла: "person.ser"
- Решение:
Сериализация списка объектов: Сериализуйте список объектов и запишите его в файл.
- Решение:java
List<Person> people = new ArrayList<>(); people.add(new Person("Alice", 30)); people.add(new Person("Bob", 25)); try (ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("people.ser"))) { oos.writeObject(people); } - Входные данные:java
// Создаем список объектов Person
- Решение:
Десериализация списка объектов: Десериализуйте список объектов из файла и выведите их.
- Решение:java
try (ObjectInputStream ois = new ObjectInputStream(new FileInputStream("people.ser"))) { List<Person> deserializedPeople = (List<Person>) ois.readObject(); for (Person p : deserializedPeople) { System.out.println("Name: " + p.name + ", Age: " + p.age); } } - Входные данные:java
// Читаем из файла: "people.ser"
- Решение:
Обработка исключений при сериализации: Обработайте исключения, возникающие при сериализации и десериализации.
- Решение:java
try { // Сериализация } catch (IOException e) { System.out.println("Serialization error: " + e.getMessage()); } try { // Десериализация } catch (ClassNotFoundException e) { System.out.println("Class not found: " + e.getMessage()); } catch (IOException e) { System.out.println("Deserialization error: " + e.getMessage()); } - Входные данные:java
// Обработка ошибок
- Решение:
ВВЕДЕНИЕ В СТРОКИ. КЛАСС STRING
Базовые задачи
Создание строки: Создайте строку и выведите ее на экран.
- Решение:java
String str = "Hello, World!"; System.out.println(str); - Входные данные:java
// Строка: "Hello, World!"
- Решение:
Длина строки: Выведите длину строки.
- Решение:java
String str = "Hello, World!"; System.out.println("Длина строки: " + str.length()); - Входные данные:java
// Строка: "Hello, World!"
- Решение:
Конкатенация строк: Объедините две строки.
- Решение:java
String str1 = "Hello"; String str2 = "World"; String result = str1 + ", " + str2 + "!"; System.out.println(result); - Входные данные:java
// Строки: "Hello", "World"
- Решение:
Извлечение подстроки: Извлеките подстроку из строки.
- Решение:java
String str = "Hello, World!"; String substring = str.substring(7, 12); System.out.println(substring); - Входные данные:java
// Строка: "Hello, World!"
- Решение:
Сравнение строк: Сравните две строки.
- Решение:java
String str1 = "Hello"; String str2 = "hello"; boolean isEqual = str1.equalsIgnoreCase(str2); System.out.println("Строки равны: " + isEqual); - Входные данные:java
// Строки: "Hello", "hello"
- Решение:
Поиск символа в строке: Найдите индекс первого вхождения символа.
- Решение:java
String str = "Hello, World!"; int index = str.indexOf('W'); System.out.println("Индекс W: " + index); - Входные данные:java
// Строка: "Hello, World!"
- Решение:
Замена символа: Замените все вхождения символа на другой.
- Решение:java
String str = "Hello, World!"; String replaced = str.replace('o', '0'); System.out.println(replaced); - Входные данные:java
// Строка: "Hello, World!"
- Решение:
Преобразование в верхний регистр: Преобразуйте строку в верхний регистр.
- Решение:java
String str = "Hello, World!"; String upperStr = str.toUpperCase(); System.out.println(upperStr); - Входные данные:java
// Строка: "Hello, World!"
- Решение:
Удаление пробелов: Удалите пробелы в начале и конце строки.
- Решение:java
String str = " Hello, World! "; String trimmed = str.trim(); System.out.println(trimmed); - Входные данные:java
// Строка: " Hello, World! "
- Решение:
Проверка на пустую строку: Проверьте, является ли строка пустой.
- Решение:java
String str = ""; boolean isEmpty = str.isEmpty(); System.out.println("Строка пуста: " + isEmpty); - Входные данные:java
// Строка: ""
- Решение:
Разбиение строки: Разбейте строку на массив подстрок.
- Решение:java
String str = "apple,banana,orange"; String[] fruits = str.split(","); for (String fruit : fruits) { System.out.println(fruit); } - Входные данные:java
// Строка: "apple,banana,orange"
- Решение:
Форматирование строки: Используйте форматирование строки.
- Решение:java
String name = "Alice"; int age = 30; String formatted = String.format("%s is %d years old.", name, age); System.out.println(formatted); - Входные данные:java
// Имя: "Alice", Возраст: 30
- Решение:
Проверка на наличие подстроки: Проверьте, содержится ли подстрока в строке.
- Решение:java
String str = "Hello, World!"; boolean contains = str.contains("World"); System.out.println("Содержит 'World': " + contains); - Входные данные:java
// Строка: "Hello, World!"
- Решение:
Конвертация массива символов в строку: Преобразуйте массив символов в строку.
- Решение:java
char[] chars = {'H', 'e', 'l', 'l', 'o'}; String str = new String(chars); System.out.println(str); - Входные данные:java
// Массив символов: {'H', 'e', 'l', 'l', 'o'}
- Решение:
Получение кода символа: Получите код символа по индексу.
- Решение:java
String str = "Hello"; int codePoint = str.codePointAt(0); System.out.println("Код первого символа: " + codePoint); - Входные данные:java
// Строка: "Hello"
- Решение:
Проверка строк на равенство с учетом регистра: Сравните две строки с учетом регистра.
- Решение:java
String str1 = "Hello"; String str2 = "hello"; boolean isEqual = str1.equals(str2); System.out.println("Строки равны (с учетом регистра): " + isEqual); - Входные данные:java
// Строки: "Hello", "hello"
- Решение:
Проверка на начало строки: Проверьте, начинается ли строка с заданной подстроки.
- Решение:java
String str = "Hello, World!"; boolean startsWith = str.startsWith("Hello"); System.out.println("Начинается с 'Hello': " + startsWith); - Входные данные:java
// Строка: "Hello, World!"
- Решение:
Проверка на конец строки: Проверьте, заканчивается ли строка на заданную подстроку.
- Решение:java
String str = "Hello, World!"; boolean endsWith = str.endsWith("World!"); System.out.println("Заканчивается на 'World!': " + endsWith); - Входные данные:java
// Строка: "Hello, World!"
- Решение:
Изменение регистра: Измените регистр всех символов в строке.
- Решение:java
String str = "HeLLo, WoRLD!"; String lower = str.toLowerCase(); String upper = str.toUpperCase(); System.out.println("Lower: " + lower); System.out.println("Upper: " + upper); - Входные данные:java
// Строка: "HeLLo, WoRLD!"
- Решение:
Проверка на симметричность: Проверьте, является ли строка палиндромом.
- Решение:java
String str = "madam"; String reversed = new StringBuilder(str).reverse().toString(); boolean isPalindrome = str.equals(reversed); System.out.println("Палиндром: " + isPalindrome); - Входные данные:java
// Строка: "madam"
- Решение:
ОСНОВНЫЕ ОПЕРАЦИИ СО СТРОКАМИ
Сложные задачи
Сравнение строк с учетом регистра: Реализуйте метод, который сравнивает две строки с учетом регистра.
- Решение:java
public static boolean compareStrings(String str1, String str2) { return str1.equals(str2); } // Пример вызова boolean result = compareStrings("Hello", "hello"); System.out.println(result); - Входные данные:java
// str1: "Hello", str2: "hello"
- Решение:
Счетчик гласных: Реализуйте метод, который считает количество гласных в строке.
- Решение:java
public static int countVowels(String str) { int count = 0; for (char c : str.toCharArray()) { if ("aeiouAEIOU".indexOf(c) != -1) { count++; } } return count; } // Пример вызова int vowelsCount = countVowels("Hello, World!"); System.out.println("Количество гласных: " + vowelsCount); - Входные данные:java
// Строка: "Hello, World!"
- Решение:
Перевернуть строку: Реализуйте метод, который переворачивает строку.
- Решение:java
public static String reverseString(String str) { return new StringBuilder(str).reverse().toString(); } // Пример вызова String reversed = reverseString("Hello"); System.out.println("Перевернутая строка: " + reversed); - Входные данные:java
// Строка: "Hello"
- Решение:
Удаление дубликатов: Реализуйте метод, который удаляет дубликаты из строки.
- Решение:java
public static String removeDuplicates(String str) { StringBuilder result = new StringBuilder(); for (char c : str.toCharArray()) { if (result.indexOf(String.valueOf(c)) == -1) { result.append(c); } } return result.toString(); } // Пример вызова String noDuplicates = removeDuplicates("Hello, World!"); System.out.println("Без дубликатов: " + noDuplicates); - Входные данные:java
// Строка: "Hello, World!"
- Решение:
Подсчет слов: Реализуйте метод, который считает количество слов в строке.
- Решение:java
public static int countWords(String str) { return str.split("\\s+").length; } // Пример вызова int wordCount = countWords("Hello, World! How are you?"); System.out.println("Количество слов: " + wordCount); - Входные данные:java
// Строка: "Hello, World! How are you?"
- Решение:
Смена регистра: Реализуйте метод, который меняет регистр каждого символа в строке.
- Решение:java
public static String swapCase(String str) { StringBuilder result = new StringBuilder(); for (char c : str.toCharArray()) { if (Character.isUpperCase(c)) { result.append(Character.toLowerCase(c)); } else { result.append(Character.toUpperCase(c)); } } return result.toString(); } // Пример вызова String swapped = swapCase("Hello, World!"); System.out.println("Смена регистра: " + swapped); - Входные данные:java
// Строка: "Hello, World!"
- Решение:
Составление анаграмм: Реализуйте метод, который проверяет, являются ли две строки анаграммами.
- Решение:java
public static boolean areAnagrams(String str1, String str2) { char[] charArray1 = str1.replaceAll("\\s+", "").toLowerCase().toCharArray(); char[] charArray2 = str2.replaceAll("\\s+", "").toLowerCase().toCharArray(); Arrays.sort(charArray1); Arrays.sort(charArray2); return Arrays.equals(charArray1, charArray2); } // Пример вызова boolean anagrams = areAnagrams("Listen", "Silent"); System.out.println("Анаграммы: " + anagrams); - Входные данные:java
// str1: "Listen", str2: "Silent"
- Решение:
Замена всех пробелов: Реализуйте метод, который заменяет все пробелы в строке на символы подчеркивания.
- Решение:java
public static String replaceSpaces(String str) { return str.replace(" ", "_"); } // Пример вызова String replacedSpaces = replaceSpaces("Hello, World!"); System.out.println("С пробелами замененными: " + replacedSpaces); - Входные данные:java
// Строка: "Hello, World!"
- Решение:
Поиск и замена: Реализуйте метод, который заменяет все вхождения подстроки на другую подстроку.
- Решение:java
public static String replaceSubstring(String str, String target, String replacement) { return str.replace(target, replacement); } // Пример вызова String newStr = replaceSubstring("Hello, World!", "World", "Java"); System.out.println("После замены: " + newStr); - Входные данные:java
// Строка: "Hello, World!", target: "World", replacement: "Java"
- Решение:
Получение символа по индексу: Реализуйте метод, который возвращает символ по заданному индексу.
- Решение:java
public static char getCharAt(String str, int index) { return str.charAt(index); } // Пример вызова char character = getCharAt("Hello, World!", 7); System.out.println("Символ на индексе 7: " + character); - Входные данные:java
// Строка: "Hello, World!", индекс: 7
- Решение:
STRINGBUFFER И STRINGBUILDER
Базовые задачи
Создание StringBuffer: Создайте объект StringBuffer и добавьте строку.
- Решение:java
StringBuffer sb = new StringBuffer("Hello"); System.out.println(sb); - Входные данные:java
// Строка: "Hello"
- Решение:
Добавление к StringBuffer: Добавьте строку к существующему StringBuffer.
- Решение:java
StringBuffer sb = new StringBuffer("Hello"); sb.append(", World!"); System.out.println(sb); - Входные данные:java
// Строка: "Hello", добавляем: ", World!"
- Решение:
Получение длины StringBuffer: Выведите длину объекта StringBuffer.
- Решение:java
StringBuffer sb = new StringBuffer("Hello"); System.out.println("Длина: " + sb.length()); - Входные данные:java
// Строка: "Hello"
- Решение:
Преобразование StringBuffer в строку: Преобразуйте StringBuffer в строку.
- Решение:java
StringBuffer sb = new StringBuffer("Hello"); String str = sb.toString(); System.out.println(str); - Входные данные:java
// Строка: "Hello"
- Решение:
Замена символа в StringBuffer: Замените символ в определенной позиции.
- Решение:java
StringBuffer sb = new StringBuffer("Hello"); sb.setCharAt(0, 'h'); System.out.println(sb); - Входные данные:java
// Строка: "Hello", индекс: 0, новый символ: 'h'
- Решение:
Удаление символа в StringBuffer: Удалите символ из StringBuffer.
- Решение:java
StringBuffer sb = new StringBuffer("Hello, World!"); sb.deleteCharAt(5); System.out.println(sb); - Входные данные:java
// Строка: "Hello, World!", индекс: 5
- Решение:
Сравнение StringBuffer с String: Сравните StringBuffer с строкой.
- Решение:java
StringBuffer sb = new StringBuffer("Hello"); boolean isEqual = sb.toString().equals("Hello"); System.out.println("Равно: " + isEqual); - Входные данные:java
// StringBuffer: "Hello", строка: "Hello"
- Решение:
Инвертирование StringBuffer: Инвертируйте содержимое StringBuffer.
- Решение:java
StringBuffer sb = new StringBuffer("Hello"); sb.reverse(); System.out.println(sb); - Входные данные:java
// Строка: "Hello"
- Решение:
Вставка в StringBuffer: Вставьте строку в определенную позицию.
- Решение:java
StringBuffer sb = new StringBuffer("Hello!"); sb.insert(5, ", World"); System.out.println(sb); - Входные данные:java
// Строка: "Hello!", вставка: ", World", индекс: 5
- Решение:
Конкатенация StringBuilder: Создайте объект StringBuilder и добавьте строку.
- Решение:java
StringBuilder sb = new StringBuilder("Hello"); sb.append(", World!"); System.out.println(sb); - Входные данные:java
// Строка: "Hello", добавляем: ", World!"
- Решение:
Сложные задачи на StringBuffer и StringBuilder
Сравнение производительности StringBuffer и StringBuilder: Реализуйте сравнение времени выполнения операций добавления для StringBuffer и StringBuilder.
- Решение:java
long startTime; // StringBuffer startTime = System.nanoTime(); StringBuffer sb = new StringBuffer(); for (int i = 0; i < 10000; i++) { sb.append("Hello"); } long bufferTime = System.nanoTime() - startTime; // StringBuilder startTime = System.nanoTime(); StringBuilder sb2 = new StringBuilder(); for (int i = 0; i < 10000; i++) { sb2.append("Hello"); } long builderTime = System.nanoTime() - startTime; System.out.println("StringBuffer time: " + bufferTime); System.out.println("StringBuilder time: " + builderTime); - Входные данные:java
// Не требуется
- Решение:
Создание палиндрома: Реализуйте метод, который проверяет, является ли строка палиндромом с использованием StringBuilder.
- Решение:java
public static boolean isPalindrome(String str) { StringBuilder sb = new StringBuilder(str); return sb.reverse().toString().equals(str); } // Пример вызова boolean palindrome = isPalindrome("madam"); System.out.println("Палиндром: " + palindrome); - Входные данные:java
// Строка: "madam"
- Решение:
Объединение строк с использованием StringBuffer: Реализуйте метод, который объединяет массив строк.
- Решение:java
public static String combineStrings(String[] strings) { StringBuffer sb = new StringBuffer(); for (String str : strings) { sb.append(str); } return sb.toString(); } // Пример вызова String[] words = {"Hello", " ", "World", "!"}; String combined = combineStrings(words); System.out.println(combined); - Входные данные:java
// Массив строк: {"Hello", " ", "World", "!"}
- Решение:
Подсчет символов: Реализуйте метод, который считает количество заданного символа в строке, используя StringBuilder.
- Решение:java
public static int countCharacter(String str, char c) { StringBuilder sb = new StringBuilder(str); int count = 0; for (int i = 0; i < sb.length(); i++) { if (sb.charAt(i) == c) { count++; } } return count; } // Пример вызова int charCount = countCharacter("Hello, World!", 'o'); System.out.println("Количество 'o': " + charCount); - Входные данные:java
// Строка: "Hello, World!", символ: 'o'
- Решение:
Создание формата: Реализуйте метод, который создает строку формата "Имя: имя, Возраст: возраст" с помощью StringBuilder.
- Решение:java
public static String formatUserInfo(String name, int age) { StringBuilder sb = new StringBuilder(); sb.append("Имя: ").append(name).append(", Возраст: ").append(age); return sb.toString(); } // Пример вызова String userInfo = formatUserInfo("Alice", 30); System.out.println(userInfo); - Входные данные:java
// Имя: "Alice", Возраст: 30
- Решение:
Изменение регистра с помощью StringBuffer: Реализуйте метод, который меняет регистр каждого символа в строке с использованием StringBuffer.
- Решение:java
public static String swapCaseBuffer(String str) { StringBuffer sb = new StringBuffer(); for (char c : str.toCharArray()) { if (Character.isUpperCase(c)) { sb.append(Character.toLowerCase(c)); } else { sb.append(Character.toUpperCase(c)); } } return sb.toString(); } // Пример вызова String swapped = swapCaseBuffer("Hello, World!"); System.out.println("Смена регистра: " + swapped); - Входные данные:java
// Строка: "Hello, World!"
- Решение:
Создание строки с заданным количеством повторений: Реализуйте метод, который создает строку, состоящую из повторяющейся подстроки заданного количества раз.
- Решение:java
public static String repeatSubstring(String substring, int count) { StringBuilder sb = new StringBuilder(); for (int i = 0; i < count; i++) { sb.append(substring); } return sb.toString(); } // Пример вызова String repeated = repeatSubstring("Hello", 3); System.out.println("Повторенная строка: " + repeated); - Входные данные:java
// Подстрока: "Hello", количество: 3
- Решение:
Поиск подстроки: Реализуйте метод, который ищет подстроку в строке с использованием StringBuilder.
- Решение:java
public static int indexOfSubstring(String str, String substring) { StringBuilder sb = new StringBuilder(str); return sb.indexOf(substring); } // Пример вызова int index = indexOfSubstring("Hello, World!", "World"); System.out.println("Индекс подстроки: " + index); - Входные данные:java
// Строка: "Hello, World!", подстрока: "World"
- Решение:
Удаление пробелов: Реализуйте метод, который удаляет все пробелы из строки с использованием StringBuilder.
- Решение:java
public static String removeSpaces(String str) { StringBuilder sb = new StringBuilder(); for (char c : str.toCharArray()) { if (c != ' ') { sb.append(c); } } return sb.toString(); } // Пример вызова String noSpaces = removeSpaces("Hello, World!"); System.out.println("Без пробелов: " + noSpaces); - Входные данные:java
// Строка: "Hello, World!"
- Решение:
Копирование содержимого: Реализуйте метод, который копирует содержимое одного StringBuilder в другой.
- Решение:java
public static StringBuilder copyBuilder(StringBuilder sb) { return new StringBuilder(sb.toString()); } // Пример вызова StringBuilder original = new StringBuilder("Hello"); StringBuilder copied = copyBuilder(original); System.out.println("Скопированная строка: " + copied); - Входные данные:java
// StringBuilder: "Hello"
- Решение:
РЕГУЛЯРНЫЕ ВЫРАЖЕНИЯ
Базовые задачи
Проверка на номер телефона: Реализуйте метод, который проверяет, является ли строка номером телефона (формат: 123-456-7890).
- Решение:java
public static boolean isValidPhoneNumber(String phone) { return phone.matches("\\d{3}-\\d{3}-\\d{4}"); } // Пример вызова boolean validPhone = isValidPhoneNumber("123-456-7890"); System.out.println("Валидный номер: " + validPhone); - Входные данные:java
// Номер телефона: "123-456-7890"
- Решение:
Проверка на адрес электронной почты: Реализуйте метод, который проверяет, является ли строка корректным адресом электронной почты.
- Решение:java
public static boolean isValidEmail(String email) { return email.matches("^[A-Za-z0-9+_.-]+@[A-Za-z0-9.-]+$"); } // Пример вызова boolean validEmail = isValidEmail("example@example.com"); System.out.println("Валидный email: " + validEmail); - Входные данные:java
// Адрес электронной почты: "example@example.com"
- Решение:
Поиск всех слов в строке: Реализуйте метод, который находит все слова в строке.
- Решение:java
public static List<String> findWords(String str) { List<String> words = new ArrayList<>(); Matcher matcher = Pattern.compile("\\b\\w+\\b").matcher(str); while (matcher.find()) { words.add(matcher.group()); } return words; } // Пример вызова List<String> words = findWords("Hello, World! How are you?"); System.out.println(words); - Входные данные:java
// Строка: "Hello, World! How are you?"
- Решение:
Замена всех цифр: Реализуйте метод, который заменяет все цифры в строке на символ 'X'.
- Решение:java
public static String replaceDigits(String str) { return str.replaceAll("\\d", "X"); } // Пример вызова String replacedDigits = replaceDigits("My number is 1234."); System.out.println(replacedDigits); - Входные данные:java
// Строка: "My number is 1234."
- Решение:
Удаление всех небуквенных символов: Реализуйте метод, который удаляет все символы, кроме букв.
- Решение:java
public static String removeNonAlphabetic(String str) { return str.replaceAll("[^a-zA-Z]", ""); } // Пример вызова String onlyLetters = removeNonAlphabetic("Hello, World! 123"); System.out.println("Только буквы: " + onlyLetters); - Входные данные:java
// Строка: "Hello, World! 123"
- Решение:
Проверка на наличие пробелов: Реализуйте метод, который проверяет, содержит ли строка пробелы.
- Решение:java
public static boolean hasSpaces(String str) { return str.matches(".*\\s.*"); } // Пример вызова boolean spaces = hasSpaces("Hello World!"); System.out.println("Содержит пробелы: " + spaces); - Входные данные:java
// Строка: "Hello World!"
- Решение:
Получение первой буквы каждого слова: Реализуйте метод, который получает первую букву каждого слова в строке.
- Решение:java
public static String getFirstLetters(String str) { StringBuilder result = new StringBuilder(); Matcher matcher = Pattern.compile("\\b\\w").matcher(str); while (matcher.find()) { result.append(matcher.group()); } return result.toString(); } // Пример вызова String firstLetters = getFirstLetters("Hello, World!"); System.out.println("Первые буквы: " + firstLetters); - Входные данные:java
// Строка: "Hello, World!"
- Решение:
Проверка на наличие специальных символов: Реализуйте метод, который проверяет, содержит ли строка специальные символы.
- Решение:java
public static boolean hasSpecialCharacters(String str) { return str.matches(".*[!@#$%^&*(),.?\":{}|<>].*"); } // Пример вызова boolean hasSpecial = hasSpecialCharacters("Hello@World!"); System.out.println("Содержит специальные символы: " + hasSpecial); - Входные данные:java
// Строка: "Hello@World!"
- Решение:
Извлечение URL из строки: Реализуйте метод, который извлекает URL из строки.
- Решение:java
public static List<String> extractUrls(String str) { List<String> urls = new ArrayList<>(); Matcher matcher = Pattern.compile("http[s]?://[^\\s]+").matcher(str); while (matcher.find()) { urls.add(matcher.group()); } return urls; } // Пример вызова List<String> urls = extractUrls("Visit us at https://example.com and http://example.org"); System.out.println(urls); - Входные данные:java
// Строка: "Visit us at https://example.com and http://example.org"
- Решение:
Изменение регистра первых букв слов: Реализуйте метод, который изменяет регистр первых букв каждого слова в строке.
- Решение:java
public static String capitalizeFirstLetters(String str) { String[] words = str.split("\\s+"); StringBuilder result = new StringBuilder(); for (String word : words) { if (word.length() > 0) { result.append(Character.toUpperCase(word.charAt(0))) .append(word.substring(1)).append(" "); } } return result.toString().trim(); } // Пример вызова String capitalized = capitalizeFirstLetters("hello world!"); System.out.println(capitalized); - Входные данные:java
// Строка: "hello world!"
- Решение:
ВВЕДЕНИЕ В ЛЯМБДА-ВЫРАЖЕНИЯ
Базовые задачи
Простое лямбда-выражение: Реализуйте лямбда-выражение, которое выводит "Hello, World!".
- Решение:java
Runnable runnable = () -> System.out.println("Hello, World!"); runnable.run(); - Входные данные:java
// Не требуется
- Решение:
Лямбда для сложения двух чисел: Создайте лямбда-выражение для сложения двух целых чисел.
- Решение:java
BiFunction<Integer, Integer, Integer> add = (a, b) -> a + b; System.out.println(add.apply(5, 10)); - Входные данные:java
// a = 5, b = 10
- Решение:
Лямбда для вычисления квадрата числа: Реализуйте лямбда-выражение, которое возвращает квадрат переданного числа.
- Решение:java
Function<Integer, Integer> square = x -> x * x; System.out.println(square.apply(4)); - Входные данные:java
// x = 4
- Решение:
Лямбда для проверки четности числа: Создайте лямбда-выражение для проверки, является ли число четным.
- Решение:java
Predicate<Integer> isEven = x -> x % 2 == 0; System.out.println(isEven.test(6)); - Входные данные:java
// x = 6
- Решение:
Лямбда для форматирования строки: Реализуйте лямбда-выражение, которое принимает строку и возвращает ее в верхнем регистре.
- Решение:java
Function<String, String> toUpperCase = s -> s.toUpperCase(); System.out.println(toUpperCase.apply("hello")); - Входные данные:java
// s = "hello"
- Решение:
Лямбда для конкатенации строк: Создайте лямбда-выражение для объединения двух строк.
- Решение:java
BiFunction<String, String, String> concatenate = (s1, s2) -> s1 + s2; System.out.println(concatenate.apply("Hello, ", "World!")); - Входные данные:java
// s1 = "Hello, ", s2 = "World!"
- Решение:
Лямбда для нахождения максимума: Реализуйте лямбда-выражение, которое возвращает максимальное из двух чисел.
- Решение:java
BiFunction<Integer, Integer, Integer> max = (a, b) -> a > b ? a : b; System.out.println(max.apply(10, 20)); - Входные данные:java
// a = 10, b = 20
- Решение:
Лямбда для вычисления длины строки: Создайте лямбда-выражение, которое возвращает длину строки.
- Решение:java
Function<String, Integer> stringLength = s -> s.length(); System.out.println(stringLength.apply("Hello")); - Входные данные:java
// s = "Hello"
- Решение:
Лямбда для проверки пустоты строки: Реализуйте лямбда-выражение для проверки, является ли строка пустой.
- Решение:java
Predicate<String> isEmpty = s -> s.isEmpty(); System.out.println(isEmpty.test("")); - Входные данные:java
// s = ""
- Решение:
Лямбда для возведения в степень: Создайте лямбда-выражение для возведения числа в заданную степень.
- Решение:java
BiFunction<Double, Integer, Double> power = (base, exponent) -> Math.pow(base, exponent); System.out.println(power.apply(2.0, 3)); - Входные данные:java
// base = 2.0, exponent = 3
- Решение:
Лямбда для умножения двух чисел: Реализуйте лямбда-выражение для умножения двух целых чисел.
- Решение:java
BiFunction<Integer, Integer, Integer> multiply = (a, b) -> a * b; System.out.println(multiply.apply(3, 4)); - Входные данные:java
// a = 3, b = 4
- Решение:
Лямбда для подсчета количества символов в строке: Создайте лямбда-выражение, которое возвращает количество символов в строке.
- Решение:java
Function<String, Integer> countChars = s -> s.length(); System.out.println(countChars.apply("Hello, World!")); - Входные данные:java
// s = "Hello, World!"
- Решение:
Лямбда для проверки наличия подстроки: Реализуйте лямбда-выражение, которое проверяет, содержится ли подстрока в строке.
- Решение:java
BiPredicate<String, String> containsSubstring = (str, sub) -> str.contains(sub); System.out.println(containsSubstring.test("Hello, World!", "World")); - Входные данные:java
// str = "Hello, World!", sub = "World"
- Решение:
Лямбда для удаления пробелов: Создайте лямбда-выражение, которое удаляет все пробелы из строки.
- Решение:java
Function<String, String> removeSpaces = s -> s.replace(" ", ""); System.out.println(removeSpaces.apply("Hello, World!")); - Входные данные:java
// s = "Hello, World!"
- Решение:
Лямбда для проверки на пустоту списка: Реализуйте лямбда-выражение для проверки, пуст ли список.
- Решение:java
Predicate<List<?>> isEmptyList = list -> list.isEmpty(); System.out.println(isEmptyList.test(new ArrayList<>())); - Входные данные:java
// Список: []
- Решение:
Лямбда для проверки длины строки: Создайте лямбда-выражение, которое проверяет, больше ли длина строки 5.
- Решение:java
Predicate<String> isLongerThanFive = s -> s.length() > 5; System.out.println(isLongerThanFive.test("Hello!")); - Входные данные:java
// s = "Hello!"
- Решение:
Лямбда для нахождения минимального значения: Реализуйте лямбда-выражение для нахождения минимального из двух чисел.
- Решение:java
BiFunction<Integer, Integer, Integer> min = (a, b) -> a < b ? a : b; System.out.println(min.apply(10, 20)); - Входные данные:java
// a = 10, b = 20
- Решение:
Лямбда для поиска символа в строке: Создайте лямбда-выражение, которое ищет символ в строке и возвращает его индекс.
- Решение:java
BiFunction<String, Character, Integer> findCharIndex = (str, ch) -> str.indexOf(ch); System.out.println(findCharIndex.apply("Hello", 'l')); - Входные данные:java
// str = "Hello", ch = 'l'
- Решение:
Лямбда для конкатенации массива строк: Реализуйте лямбда-выражение для конкатенации массива строк в одну строку.
- Решение:java
Function<String[], String> concatenateArray = arr -> String.join("", arr); System.out.println(concatenateArray.apply(new String[]{"Hello, ", "World!"})); - Входные данные:java
// arr = {"Hello, ", "World!"}
- Решение:
Лямбда для замены символа в строке: Создайте лямбда-выражение, которое заменяет указанный символ в строке.
- Решение:java
BiFunction<String, Character, String> replaceChar = (str, ch) -> str.replace(ch, '*'); System.out.println(replaceChar.apply("Hello, World!", 'o')); - Входные данные:java
// str = "Hello, World!", ch = 'o'
- Решение:
Сложные задачи
Лямбда для сортировки списка: Реализуйте метод, который принимает список строк и сортирует его с помощью лямбда-выражения.
- Решение:java
List<String> list = Arrays.asList("Banana", "Apple", "Cherry"); list.sort((s1, s2) -> s1.compareTo(s2)); System.out.println(list); - Входные данные:java
// Список: ["Banana", "Apple", "Cherry"]
- Решение:
Лямбда для фильтрации списка: Создайте метод, который фильтрует список чисел, оставляя только четные числа.
- Решение:java
List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5); List<Integer> evenNumbers = numbers.stream().filter(n -> n % 2 == 0).collect(Collectors.toList()); System.out.println(evenNumbers); - Входные данные:java
// Список: [1, 2, 3, 4, 5]
- Решение:
Лямбда для преобразования списка строк в их длины: Реализуйте метод, который преобразует список строк в список их длин.
- Решение:java
List<String> words = Arrays.asList("Java", "Lambda", "Expressions"); List<Integer> lengths = words.stream().map(String::length).collect(Collectors.toList()); System.out.println(lengths); - Входные данные:java
// Список: ["Java", "Lambda", "Expressions"]
- Решение:
Лямбда для вычисления факториала: Создайте метод, который вычисляет факториал числа с использованием рекурсии и лямбда-выражения.
- Решение:java
Function<Integer, Integer> factorial = new Function<Integer, Integer>() { @Override public Integer apply(Integer n) { return (n == 0) ? 1 : n * apply(n - 1); } }; System.out.println(factorial.apply(5)); - Входные данные:java
// n = 5
- Решение:
Лямбда для подсчета количества вхождений: Реализуйте метод, который считает количество вхождений символа в строке.
- Решение:java
BiFunction<String, Character, Long> countOccurrences = (str, ch) -> str.chars().filter(c -> c == ch).count(); System.out.println(countOccurrences.apply("Hello, World!", 'o')); - Входные данные:java
// str = "Hello, World!", ch = 'o'
- Решение:
Лямбда для нахождения максимального значения в списке: Создайте метод, который находит максимальное значение в списке.
- Решение:java
List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5); Integer maxNumber = numbers.stream().max(Integer::compare).orElse(null); System.out.println(maxNumber); - Входные данные:java
// Список: [1, 2, 3, 4, 5]
- Решение:
Лямбда для объединения строк с разделителем: Реализуйте метод, который объединяет список строк с указанным разделителем.
- Решение:java
List<String> strings = Arrays.asList("Java", "Lambda", "Expressions"); String result = strings.stream().collect(Collectors.joining(", ")); System.out.println(result); - Входные данные:java
// Список: ["Java", "Lambda", "Expressions"], разделитель: ", "
- Решение:
Лямбда для создания карты частоты элементов: Создайте метод, который создает карту, отображающую количество вхождений каждого элемента в списке.
- Решение:java
List<String> words = Arrays.asList("apple", "banana", "apple", "orange", "banana", "banana"); Map<String, Long> frequencyMap = words.stream().collect(Collectors.groupingBy(Function.identity(), Collectors.counting())); System.out.println(frequencyMap); - Входные данные:java
// Список: ["apple", "banana", "apple", "orange", "banana", "banana"]
- Решение:
Лямбда для создания списка квадратов чисел: Реализуйте метод, который создает список квадратов чисел из исходного списка.
- Решение:java
List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5); List<Integer> squares = numbers.stream().map(n -> n * n).collect(Collectors.toList()); System.out.println(squares); - Входные данные:java
// Список: [1, 2, 3, 4, 5]
- Решение:
Лямбда для сортировки списка объектов: Создайте класс
Personи реализуйте лямбда-выражение для сортировки списка объектов этого класса по имени.- Решение:java
class Person { String name; int age; Person(String name, int age) { this.name = name; this.age = age; } @Override public String toString() { return name + " (" + age + ")"; } } List<Person> people = Arrays.asList(new Person("Alice", 30), new Person("Bob", 25), new Person("Charlie", 35)); people.sort((p1, p2) -> p1.name.compareTo(p2.name)); System.out.println(people); - Входные данные:java
// Список: [new Person("Alice", 30), new Person("Bob", 25), new Person("Charlie", 35)]
- Решение:
КЛАСС THREAD
Базовые задачи
Создание простого потока: Создайте поток, который выводит "Hello from Thread!".
- Решение:java
class HelloThread extends Thread { @Override public void run() { System.out.println("Hello from Thread!"); } } public class Main { public static void main(String[] args) { HelloThread thread = new HelloThread(); thread.start(); } } - Входные данные:java
// Не требуется
- Решение:
Создание потока с использованием Runnable: Реализуйте поток, который выводит числа от 1 до 5.
- Решение:java
class NumberRunnable implements Runnable { @Override public void run() { for (int i = 1; i <= 5; i++) { System.out.println(i); } } } public class Main { public static void main(String[] args) { Thread thread = new Thread(new NumberRunnable()); thread.start(); } } - Входные данные:java
// Не требуется
- Решение:
Создание нескольких потоков: Создайте три потока, которые выводят свои имена.
- Решение:java
class NameRunnable implements Runnable { private String name; public NameRunnable(String name) { this.name = name; } @Override public void run() { System.out.println("My name is " + name); } } public class Main { public static void main(String[] args) { Thread thread1 = new Thread(new NameRunnable("Alice")); Thread thread2 = new Thread(new NameRunnable("Bob")); Thread thread3 = new Thread(new NameRunnable("Charlie")); thread1.start(); thread2.start(); thread3.start(); } } - Входные данные:java
// Не требуется
- Решение:
Использование метода sleep: Создайте поток, который выводит числа от 1 до 5 с паузой в 1 секунду.
- Решение:java
class SleepRunnable implements Runnable { @Override public void run() { for (int i = 1; i <= 5; i++) { System.out.println(i); try { Thread.sleep(1000); } catch (InterruptedException e) { Thread.currentThread().interrupt(); } } } } public class Main { public static void main(String[] args) { Thread thread = new Thread(new SleepRunnable()); thread.start(); } } - Входные данные:java
// Не требуется
- Решение:
Получение идентификатора потока: Создайте поток, который выводит свой идентификатор.
- Решение:java
class IDRunnable implements Runnable { @Override public void run() { System.out.println("Thread ID: " + Thread.currentThread().getId()); } } public class Main { public static void main(String[] args) { Thread thread = new Thread(new IDRunnable()); thread.start(); } } - Входные данные:java
// Не требуется
- Решение:
Запуск потока несколько раз: Попробуйте запустить один и тот же поток несколько раз (ожидается исключение).
- Решение:java
class RunOnce implements Runnable { @Override public void run() { System.out.println("Running..."); } } public class Main { public static void main(String[] args) { RunOnce runOnce = new RunOnce(); Thread thread = new Thread(runOnce); thread.start(); // Попытка запустить тот же поток снова thread.start(); // Это вызовет IllegalThreadStateException } } - Входные данные:java
// Не требуется
- Решение:
Использование метода join: Создайте два потока и дождитесь завершения первого перед запуском второго.
- Решение:java
class TaskRunnable implements Runnable { private String name; public TaskRunnable(String name) { this.name = name; } @Override public void run() { System.out.println(name + " is running."); } } public class Main { public static void main(String[] args) throws InterruptedException { Thread thread1 = new Thread(new TaskRunnable("Thread 1")); Thread thread2 = new Thread(new TaskRunnable("Thread 2")); thread1.start(); thread1.join(); // Ждем завершения первого потока thread2.start(); } } - Входные данные:java
// Не требуется
- Решение:
Создание потока с приоритетом: Создайте поток с высоким приоритетом и запустите его.
- Решение:java
class PriorityRunnable implements Runnable { @Override public void run() { System.out.println("High priority thread is running."); } } public class Main { public static void main(String[] args) { Thread thread = new Thread(new PriorityRunnable()); thread.setPriority(Thread.MAX_PRIORITY); thread.start(); } } - Входные данные:java
// Не требуется
- Решение:
Использование метода yield: Реализуйте поток, который использует метод yield для временного освобождения процессорного времени.
- Решение:java
class YieldRunnable implements Runnable { @Override public void run() { for (int i = 0; i < 5; i++) { System.out.println(Thread.currentThread().getName() + " yielded."); Thread.yield(); } } } public class Main { public static void main(String[] args) { Thread thread1 = new Thread(new YieldRunnable()); Thread thread2 = new Thread(new YieldRunnable()); thread1.start(); thread2.start(); } } - Входные данные:java
// Не требуется
- Решение:
Проверка состояния потока: Реализуйте метод, который проверяет состояние потока.
- Решение:java
class StateRunnable implements Runnable { @Override public void run() { try { Thread.sleep(2000); } catch (InterruptedException e) { Thread.currentThread().interrupt(); } } } public class Main { public static void main(String[] args) throws InterruptedException { Thread thread = new Thread(new StateRunnable()); System.out.println("Thread state before start: " + thread.getState()); thread.start(); System.out.println("Thread state after start: " + thread.getState()); thread.join(); System.out.println("Thread state after completion: " + thread.getState()); } } - Входные данные:java
// Не требуется
- Решение:
Потоки с использованием статического метода: Создайте статический метод, который выполняется в потоке.
- Решение:java
class StaticMethodRunnable { public static void printMessage() { System.out.println("Hello from static method!"); } } public class Main { public static void main(String[] args) { Thread thread = new Thread(StaticMethodRunnable::printMessage); thread.start(); } } - Входные данные:java
// Не требуется
- Решение:
Использование локальных переменных: Создайте поток, который использует локальную переменную.
- Решение:java
public class Main { public static void main(String[] args) { final String message = "Hello from local variable!"; Thread thread = new Thread(() -> System.out.println(message)); thread.start(); } } - Входные данные:java
// Не требуется
- Решение:
Потоки с обработкой исключений: Создайте поток, который обрабатывает исключение.
- Решение:java
class ExceptionRunnable implements Runnable { @Override public void run() { try { throw new RuntimeException("Exception in thread"); } catch (RuntimeException e) { System.out.println(e.getMessage()); } } } public class Main { public static void main(String[] args) { Thread thread = new Thread(new ExceptionRunnable()); thread.start(); } } - Входные данные:java
// Не требуется
- Решение:
Состояние потока при завершении: Создайте поток и проверьте его состояние после завершения.
- Решение:java
class FinishRunnable implements Runnable { @Override public void run() { System.out.println("Thread is running."); } } public class Main { public static void main(String[] args) throws InterruptedException { Thread thread = new Thread(new FinishRunnable()); thread.start(); thread.join(); System.out.println("Thread state after completion: " + thread.getState()); } } - Входные данные:java
// Не требуется
- Решение:
Создание потоков через лямбда-выражения: Используйте лямбда-выражение для создания потока.
- Решение:java
public class Main { public static void main(String[] args) { Thread thread = new Thread(() -> System.out.println("Thread created with lambda!")); thread.start(); } } - Входные данные:java
// Не требуется
- Решение:
Изменение приоритета потока: Измените приоритет потока и запустите его.
- Решение:java
class PriorityChangeRunnable implements Runnable { @Override public void run() { System.out.println("Running with priority: " + Thread.currentThread().getPriority()); } } public class Main { public static void main(String[] args) { Thread thread = new Thread(new PriorityChangeRunnable()); thread.setPriority(Thread.MIN_PRIORITY); thread.start(); } } - Входные данные:java
// Не требуется
- Решение:
Проверка прерывания потока: Создайте поток, который проверяет состояние прерывания.
- Решение:java
class InterruptCheckRunnable implements Runnable { @Override public void run() { while (!Thread.currentThread().isInterrupted()) { System.out.println("Running..."); try { Thread.sleep(500); } catch (InterruptedException e) { Thread.currentThread().interrupt(); } } System.out.println("Thread interrupted!"); } } public class Main { public static void main(String[] args) throws InterruptedException { Thread thread = new Thread(new InterruptCheckRunnable()); thread.start(); Thread.sleep(1500); thread.interrupt(); } } - Входные данные:java
// Не требуется
- Решение:
Потоки с общими данными: Создайте несколько потоков, которые изменяют общую переменную.
- Решение:java
class SharedCounter { private int count = 0; public synchronized void increment() { count++; } public int getCount() { return count; } } public class Main { public static void main(String[] args) throws InterruptedException { SharedCounter counter = new SharedCounter(); Runnable task = () -> { for (int i = 0; i < 1000; i++) { counter.increment(); } }; Thread thread1 = new Thread(task); Thread thread2 = new Thread(task); thread1.start(); thread2.start(); thread1.join(); thread2.join(); System.out.println("Final count: " + counter.getCount()); } } - Входные данные:java
// Не требуется
- Решение:
Поток, работающий с массивом: Создайте поток, который суммирует элементы массива.
- Решение:java
class SumArrayRunnable implements Runnable { private int[] numbers; public SumArrayRunnable(int[] numbers) { this.numbers = numbers; } @Override public void run() { int sum = 0; for (int number : numbers) { sum += number; } System.out.println("Sum: " + sum); } } public class Main { public static void main(String[] args) { int[] numbers = {1, 2, 3, 4, 5}; Thread thread = new Thread(new SumArrayRunnable(numbers)); thread.start(); } } - Входные данные:java
// Массив: {1, 2, 3, 4, 5}
- Решение:
Создание потока, который генерирует случайные числа: Реализуйте поток, который генерирует и выводит случайные числа.
- Решение:java
import java.util.Random; class RandomNumberRunnable implements Runnable { @Override public void run() { Random random = new Random(); for (int i = 0; i < 5; i++) { System.out.println("Random number: " + random.nextInt(100)); try { Thread.sleep(1000); } catch (InterruptedException e) { Thread.currentThread().interrupt(); } } } } public class Main { public static void main(String[] args) { Thread thread = new Thread(new RandomNumberRunnable()); thread.start(); } } - Входные данные:java
// Не требуется
- Решение:
Сложные задачи
Завершение и прерывание потока: Реализуйте механизм, который запускает поток, который прерывается по истечении времени.
- Решение:java
class InterruptibleRunnable implements Runnable { @Override public void run() { try { while (true) { System.out.println("Running..."); Thread.sleep(1000); } } catch (InterruptedException e) { System.out.println("Thread interrupted!"); } } } public class Main { public static void main(String[] args) throws InterruptedException { Thread thread = new Thread(new InterruptibleRunnable()); thread.start(); Thread.sleep(3000); thread.interrupt(); } } - Входные данные:java
// Не требуется
- Решение:
Синхронизация потоков: Реализуйте класс с методом, который может быть выполнен только одним потоком одновременно.
- Решение:java
class SynchronizedCounter { private int count = 0; public synchronized void increment() { count++; } public int getCount() { return count; } } public class Main { public static void main(String[] args) throws InterruptedException { SynchronizedCounter counter = new SynchronizedCounter(); Runnable task = () -> { for (int i = 0; i < 1000; i++) { counter.increment(); } }; Thread thread1 = new Thread(task); Thread thread2 = new Thread(task); thread1.start(); thread2.start(); thread1.join(); thread2.join(); System.out.println("Final count: " + counter.getCount()); } } - Входные данные:java
// Не требуется
- Решение:
Использование wait и notify: Реализуйте систему производитель-потребитель с использованием методов wait и notify.
- Решение:java
class SharedResource { private int data; private boolean available = false; public synchronized int consume() throws InterruptedException { while (!available) { wait(); } available = false; notifyAll(); return data; } public synchronized void produce(int value) throws InterruptedException { while (available) { wait(); } data = value; available = true; notifyAll(); } } public class Main { public static void main(String[] args) { SharedResource resource = new SharedResource(); Runnable producer = () -> { for (int i = 0; i < 5; i++) { try { resource.produce(i); System.out.println("Produced: " + i); } catch (InterruptedException e) { Thread.currentThread().interrupt(); } } }; Runnable consumer = () -> { for (int i = 0; i < 5; i++) { try { int value = resource.consume(); System.out.println("Consumed: " + value); } catch (InterruptedException e) { Thread.currentThread().interrupt(); } } }; new Thread(producer).start(); new Thread(consumer).start(); } } - Входные данные:java
// Не требуется
- Решение:
Семафор для контроля доступа: Создайте семафор, который контролирует доступ к ресурсу.
- Решение:java
import java.util.concurrent.Semaphore; class Resource { private Semaphore semaphore = new Semaphore(1); public void access() { try { semaphore.acquire(); System.out.println("Accessing resource: " + Thread.currentThread().getName()); Thread.sleep(1000); } catch (InterruptedException e) { Thread.currentThread().interrupt(); } finally { semaphore.release(); } } } public class Main { public static void main(String[] args) { Resource resource = new Resource(); Runnable task = resource::access; for (int i = 0; i < 5; i++) { new Thread(task).start(); } } } - Входные данные:java
// Не требуется
- Решение:
Обмен между потоками с Exchanger: Реализуйте программу, использующую класс Exchanger для обмена данными между двумя потоками.
- Решение:java
import java.util.concurrent.Exchanger; class DataExchanger { private Exchanger<String> exchanger = new Exchanger<>(); public void exchangeData() { try { String data = "Data from " + Thread.currentThread().getName(); String received = exchanger.exchange(data); System.out.println(Thread.currentThread().getName() + " received: " + received); } catch (InterruptedException e) { Thread.currentThread().interrupt(); } } } public class Main { public static void main(String[] args) { DataExchanger dataExchanger = new DataExchanger(); Runnable task1 = dataExchanger::exchangeData; Runnable task2 = dataExchanger::exchangeData; new Thread(task1).start(); new Thread(task2).start(); } } - Входные данные:java
// Не требуется
- Решение:
Использование класса Phaser: Реализуйте программу с использованием класса Phaser для синхронизации потоков.
- Решение:java
import java.util.concurrent.Phaser; class PhaserExample { private Phaser phaser = new Phaser(1); public void runTask(int id) { System.out.println("Task " + id + " is waiting at phase " + phaser.getPhase()); phaser.arriveAndAwaitAdvance(); // Ждем других задач System.out.println("Task " + id + " completed at phase " + phaser.getPhase()); } public void startTasks(int numberOfTasks) { for (int i = 1; i <= numberOfTasks; i++) { final int id = i; new Thread(() -> runTask(id)).start(); phaser.register(); // Регистрация нового потока } phaser.arriveAndDeregister(); // Уменьшаем количество потоков } } public class Main { public static void main(String[] args) { PhaserExample example = new PhaserExample(); example.startTasks(3); } } - Входные данные:java
// Не требуется
- Решение:
Использование ReentrantLock: Реализуйте класс с использованием ReentrantLock для синхронизации потоков.
- Решение:java
import java.util.concurrent.locks.ReentrantLock; class LockCounter { private int count = 0; private ReentrantLock lock = new ReentrantLock(); public void increment() { lock.lock(); try { count++; } finally { lock.unlock(); } } public int getCount() { return count; } } public class Main { public static void main(String[] args) throws InterruptedException { LockCounter counter = new LockCounter(); Runnable task = () -> { for (int i = 0; i < 1000; i++) { counter.increment(); } }; Thread thread1 = new Thread(task); Thread thread2 = new Thread(task); thread1.start(); thread2.start(); thread1.join(); thread2.join(); System.out.println("Final count: " + counter.getCount()); } } - Входные данные:java
// Не требуется
- Решение:
Условия в блокировках: Реализуйте систему с использованием условий в блокировках.
- Решение:java
import java.util.concurrent.locks.Condition; import java.util.concurrent.locks.ReentrantLock; class ConditionExample { private ReentrantLock lock = new ReentrantLock(); private Condition condition = lock.newCondition(); private boolean isReady = false; public void waitUntilReady() throws InterruptedException { lock.lock(); try { while (!isReady) { condition.await(); } System.out.println("Thread is proceeding."); } finally { lock.unlock(); } } public void makeReady() { lock.lock(); try { isReady = true; condition.signalAll(); } finally { lock.unlock(); } } } public class Main { public static void main(String[] args) throws InterruptedException { ConditionExample example = new ConditionExample(); Runnable waitTask = example::waitUntilReady; new Thread(waitTask).start(); Thread.sleep(2000); example.makeReady(); } } - Входные данные:java
// Не требуется
- Решение:
Поток, работающий с коллекцией: Создайте многопоточный класс, который использует коллекцию для хранения данных.
- Решение:java
import java.util.ArrayList; import java.util.Collections; import java.util.List; class CollectionExample { private List<Integer> list = Collections.synchronizedList(new ArrayList<>()); public void addData(int value) { list.add(value); } public void printData() { for (Integer value : list) { System.out.println(value); } } } public class Main { public static void main(String[] args) throws InterruptedException { CollectionExample example = new CollectionExample(); Runnable task = () -> { for (int i = 0; i < 10; i++) { example.addData((int) (Math.random() * 100)); } }; Thread thread1 = new Thread(task); Thread thread2 = new Thread(task); thread1.start(); thread2.start(); thread1.join(); thread2.join(); example.printData(); } } - Входные данные:java
// Не требуется
- Решение:
Обработка ошибок в потоках: Реализуйте механизм обработки ошибок, возникающих в потоках.
- Решение:java
class ErrorRunnable implements Runnable { @Override public void run() { try { throw new RuntimeException("Error in thread"); } catch (RuntimeException e) { System.out.println("Caught exception: " + e.getMessage()); } } } public class Main { public static void main(String[] args) { Thread thread = new Thread(new ErrorRunnable()); thread.start(); } } - Входные данные:java
// Не требуется
- Решение:
ВВЕДЕНИЕ В STREAM API
Базовые задачи
Создание простого потока данных: Создайте поток данных из массива чисел и выведите его на экран.
- Решение:java
import java.util.Arrays; import java.util.stream.Stream; public class Main { public static void main(String[] args) { int[] numbers = {1, 2, 3, 4, 5}; Stream<int[]> stream = Arrays.stream(new int[][]{numbers}); stream.forEach(arr -> System.out.println(Arrays.toString(arr))); } } - Входные данные:java
// Массив: {1, 2, 3, 4, 5}
- Решение:
Преобразование списка в поток: Создайте список строк и преобразуйте его в поток.
- Решение:java
import java.util.Arrays; import java.util.List; public class Main { public static void main(String[] args) { List<String> names = Arrays.asList("Alice", "Bob", "Charlie"); names.stream().forEach(System.out::println); } } - Входные данные:java
// Список: {"Alice", "Bob", "Charlie"}
- Решение:
Фильтрация четных чисел: Создайте поток из чисел и отфильтруйте четные числа.
- Решение:java
import java.util.Arrays; public class Main { public static void main(String[] args) { int[] numbers = {1, 2, 3, 4, 5, 6}; Arrays.stream(numbers) .filter(n -> n % 2 == 0) .forEach(System.out::println); } } - Входные данные:java
// Массив: {1, 2, 3, 4, 5, 6}
- Решение:
Отображение элементов: Преобразуйте поток строк в их длины.
- Решение:java
import java.util.Arrays; public class Main { public static void main(String[] args) { String[] words = {"apple", "banana", "cherry"}; Arrays.stream(words) .map(String::length) .forEach(System.out::println); } } - Входные данные:java
// Массив: {"apple", "banana", "cherry"}
- Решение:
Сортировка чисел: Создайте поток чисел и отсортируйте их по возрастанию.
- Решение:java
import java.util.Arrays; public class Main { public static void main(String[] args) { int[] numbers = {5, 3, 8, 1, 2}; Arrays.stream(numbers) .sorted() .forEach(System.out::println); } } - Входные данные:java
// Массив: {5, 3, 8, 1, 2}
- Решение:
Получение уникальных элементов: Создайте поток и получите уникальные элементы из списка.
- Решение:java
import java.util.Arrays; import java.util.List; public class Main { public static void main(String[] args) { List<Integer> numbers = Arrays.asList(1, 2, 2, 3, 4, 4, 5); numbers.stream() .distinct() .forEach(System.out::println); } } - Входные данные:java
// Список: {1, 2, 2, 3, 4, 4, 5}
- Решение:
Получение первых элементов: Используйте метод limit для получения первых трех элементов.
- Решение:java
import java.util.Arrays; public class Main { public static void main(String[] args) { int[] numbers = {1, 2, 3, 4, 5, 6}; Arrays.stream(numbers) .limit(3) .forEach(System.out::println); } } - Входные данные:java
// Массив: {1, 2, 3, 4, 5, 6}
- Решение:
Пропуск элементов: Используйте метод skip для пропуска первых двух элементов.
- Решение:java
import java.util.Arrays; public class Main { public static void main(String[] args) { int[] numbers = {1, 2, 3, 4, 5}; Arrays.stream(numbers) .skip(2) .forEach(System.out::println); } } - Входные данные:java
// Массив: {1, 2, 3, 4, 5}
- Решение:
Объединение потоков: Объедините два потока данных в один.
- Решение:java
import java.util.Arrays; import java.util.List; public class Main { public static void main(String[] args) { List<String> list1 = Arrays.asList("A", "B"); List<String> list2 = Arrays.asList("C", "D"); Stream.concat(list1.stream(), list2.stream()) .forEach(System.out::println); } } - Входные данные:java
// Списки: {"A", "B"}, {"C", "D"}
- Решение:
Использование метода collect: Соберите элементы потока в список.
- Решение:java
import java.util.Arrays; import java.util.List; import java.util.stream.Collectors; public class Main { public static void main(String[] args) { List<String> names = Arrays.asList("Alice", "Bob", "Charlie"); List<String> collected = names.stream() .collect(Collectors.toList()); System.out.println(collected); } } - Входные данные:java
// Список: {"Alice", "Bob", "Charlie"}
- Решение:
Сведение элементов: Сложите все элементы потока.
- Решение:java
import java.util.Arrays; public class Main { public static void main(String[] args) { int[] numbers = {1, 2, 3, 4, 5}; int sum = Arrays.stream(numbers) .sum(); System.out.println("Sum: " + sum); } } - Входные данные:java
// Массив: {1, 2, 3, 4, 5}
- Решение:
Использование метода reduce: Найдите произведение элементов потока.
- Решение:java
import java.util.Arrays; public class Main { public static void main(String[] args) { int[] numbers = {1, 2, 3, 4, 5}; int product = Arrays.stream(numbers) .reduce(1, (a, b) -> a * b); System.out.println("Product: " + product); } } - Входные данные:java
// Массив: {1, 2, 3, 4, 5}
- Решение:
Использование Optional: Создайте объект Optional и обработайте его.
- Решение:java
import java.util.Optional; public class Main { public static void main(String[] args) { Optional<String> optional = Optional.of("Hello, World!"); optional.ifPresent(System.out::println); } } - Входные данные:java
// Не требуется
- Решение:
Группировка элементов: Группируйте элементы по длине строки.
- Решение:java
import java.util.Arrays; import java.util.List; import java.util.Map; import java.util.stream.Collectors; public class Main { public static void main(String[] args) { List<String> words = Arrays.asList("apple", "banana", "pear", "kiwi"); Map<Integer, List<String>> grouped = words.stream() .collect(Collectors.groupingBy(String::length)); System.out.println(grouped); } } - Входные данные:java
// Список: {"apple", "banana", "pear", "kiwi"}
- Решение:
Параллельный поток: Создайте параллельный поток для выполнения операций.
- Решение:java
import java.util.Arrays; public class Main { public static void main(String[] args) { int[] numbers = {1, 2, 3, 4, 5}; Arrays.stream(numbers) .parallel() .forEach(n -> System.out.println(Thread.currentThread().getName() + ": " + n)); } } - Входные данные:java
// Массив: {1, 2, 3, 4, 5}
- Решение:
Параллельная сортировка: Сортируйте массив в параллельном потоке.
- Решение:java
import java.util.Arrays; public class Main { public static void main(String[] args) { int[] numbers = {5, 3, 8, 1, 2}; Arrays.parallelSort(numbers); System.out.println(Arrays.toString(numbers)); } } - Входные данные:java
// Массив: {5, 3, 8, 1, 2}
- Решение:
Параллельное вычисление суммы: Используйте параллельный поток для вычисления суммы.
- Решение:java
import java.util.Arrays; public class Main { public static void main(String[] args) { int[] numbers = {1, 2, 3, 4, 5}; int sum = Arrays.stream(numbers).parallel().sum(); System.out.println("Sum: " + sum); } } - Входные данные:java
// Массив: {1, 2, 3, 4, 5}
- Решение:
Параллельное отображение: Примените отображение в параллельном потоке.
- Решение:java
import java.util.Arrays; public class Main { public static void main(String[] args) { String[] words = {"hello", "world"}; Arrays.stream(words) .parallel() .map(String::toUpperCase) .forEach(System.out::println); } } - Входные данные:java
// Массив: {"hello", "world"}
- Решение:
Использование метода allMatch: Проверьте, соответствуют ли все элементы условию.
- Решение:java
import java.util.Arrays; public class Main { public static void main(String[] args) { int[] numbers = {2, 4, 6, 8}; boolean allEven = Arrays.stream(numbers).allMatch(n -> n % 2 == 0); System.out.println("All are even: " + allEven); } } - Входные данные:java
// Массив: {2, 4, 6, 8}
- Решение:
Использование метода anyMatch: Проверьте, есть ли хотя бы один элемент, соответствующий условию.
- Решение:java
import java.util.Arrays; public class Main { public static void main(String[] args) { int[] numbers = {1, 3, 5, 7}; boolean anyEven = Arrays.stream(numbers).anyMatch(n -> n % 2 == 0); System.out.println("Any are even: " + anyEven); } } - Входные данные:java
// Массив: {1, 3, 5, 7}
- Решение:
Сложные задачи
Сложение чисел с использованием reduce: Используйте метод reduce для сложения чисел с учетом условий.
- Решение:java
import java.util.Arrays; public class Main { public static void main(String[] args) { int[] numbers = {1, 2, 3, 4, 5}; int sum = Arrays.stream(numbers) .filter(n -> n > 2) .reduce(0, Integer::sum); System.out.println("Sum of numbers greater than 2: " + sum); } } - Входные данные:java
// Массив: {1, 2, 3, 4, 5}
- Решение:
Группировка и подсчет: Группируйте слова по длине и подсчитайте количество слов каждой длины.
- Решение:java
import java.util.Arrays; import java.util.List; import java.util.Map; import java.util.stream.Collectors; public class Main { public static void main(String[] args) { List<String> words = Arrays.asList("apple", "banana", "kiwi", "pear", "peach"); Map<Integer, Long> lengthCount = words.stream() .collect(Collectors.groupingBy(String::length, Collectors.counting())); System.out.println(lengthCount); } } - Входные данные:java
// Список: {"apple", "banana", "kiwi", "pear", "peach"}
- Решение:
Создание Map из списка объектов: Создайте класс
Person, создайте список и соберите его в Map.- Решение:java
import java.util.Arrays; import java.util.List; import java.util.Map; import java.util.stream.Collectors; class Person { String name; int age; Person(String name, int age) { this.name = name; this.age = age; } public String getName() { return name; } } public class Main { public static void main(String[] args) { List<Person> people = Arrays.asList(new Person("Alice", 25), new Person("Bob", 30)); Map<String, Integer> nameToAge = people.stream() .collect(Collectors.toMap(Person::getName, person -> person.age)); System.out.println(nameToAge); } } - Входные данные:java
// Список объектов Person: {{"Alice", 25}, {"Bob", 30}}
- Решение:
Фильтрация и отображение объектов: Создайте класс
Bookи отфильтруйте книги по автору.- Решение:java
import java.util.Arrays; import java.util.List; class Book { String title; String author; Book(String title, String author) { this.title = title; this.author = author; } } public class Main { public static void main(String[] args) { List<Book> books = Arrays.asList( new Book("Book A", "Author 1"), new Book("Book B", "Author 2"), new Book("Book C", "Author 1") ); books.stream() .filter(book -> "Author 1".equals(book.author)) .map(book -> book.title) .forEach(System.out::println); } } - Входные данные:java
// Список объектов Book: {{"Book A", "Author 1"}, {"Book B", "Author 2"}, {"Book C", "Author 1"}}
- Решение:
Комплексная группировка: Группируйте людей по возрасту и подсчитывайте количество людей в каждой группе.
- Решение:java
import java.util.Arrays; import java.util.List; import java.util.Map; import java.util.stream.Collectors; class Person { String name; int age; Person(String name, int age) { this.name = name; this.age = age; } public int getAge() { return age; } } public class Main { public static void main(String[] args) { List<Person> people = Arrays.asList( new Person("Alice", 25), new Person("Bob", 30), new Person("Charlie", 25) ); Map<Integer, Long> ageGroupCount = people.stream() .collect(Collectors.groupingBy(Person::getAge, Collectors.counting())); System.out.println(ageGroupCount); } } - Входные данные:java
// Список объектов Person: {{"Alice", 25}, {"Bob", 30}, {"Charlie", 25}}
- Решение:
Использование flatMap: Создайте поток строк, который объединяет несколько списков.
- Решение:java
import java.util.Arrays; import java.util.List; public class Main { public static void main(String[] args) { List<List<String>> lists = Arrays.asList( Arrays.asList("A", "B"), Arrays.asList("C", "D") ); lists.stream() .flatMap(List::stream) .forEach(System.out::println); } } - Входные данные:java
// Список списков: {{"A", "B"}, {"C", "D"}}
- Решение:
Использование peek для отладки: Используйте метод peek для отладки потока.
- Решение:java
import java.util.Arrays; public class Main { public static void main(String[] args) { int[] numbers = {1, 2, 3, 4, 5}; Arrays.stream(numbers) .peek(n -> System.out.println("Processing: " + n)) .map(n -> n * 2) .forEach(System.out::println); } } - Входные данные:java
// Массив: {1, 2, 3, 4, 5}
- Решение:
Применение оператора collect: Соберите строки в единое предложение.
- Решение:java
import java.util.Arrays; import java.util.List; import java.util.stream.Collectors; public class Main { public static void main(String[] args) { List<String> words = Arrays.asList("Java", "is", "fun"); String sentence = words.stream().collect(Collectors.joining(" ")) + "."; System.out.println(sentence); } } - Входные данные:java
// Список: {"Java", "is", "fun"}
- Решение:
Использование Optional для обработки значений: Обработайте значение, используя Optional.
- Решение:java
import java.util.Optional; public class Main { public static void main(String[] args) { Optional<String> name = Optional.of("Alice"); String greeting = name.map(n -> "Hello, " + n).orElse("Hello, Guest!"); System.out.println(greeting); } } - Входные данные:java
// Не требуется
- Решение:
Создание параллельных потоков с использованием методов: Создайте параллельный поток, который производит вычисления.
- Решение:java
import java.util.stream.IntStream; public class Main { public static void main(String[] args) { int sum = IntStream.range(1, 100).parallel().sum(); System.out.println("Sum from 1 to 99: " + sum); } } - Входные данные:java
// Не требуется
- Решение:
СОЗДАНИЕ МОДУЛЯ
Базовые задачи
Создание простого модуля: Создайте модуль с именем
my.module, который содержит простой классHelloс методомsayHello(), возвращающим строку "Hello, World!".- Решение:java
// my.module/src/Hello.java module my.module { } public class Hello { public String sayHello() { return "Hello, World!"; } } - Входные данные:java
// Не требуется
- Решение:
Импорт класса из модуля: Создайте другой модуль
app.module, который используетHelloизmy.module.- Решение:java
// app.module/src/App.java module app.module { requires my.module; } import my.module.Hello; public class App { public static void main(String[] args) { Hello hello = new Hello(); System.out.println(hello.sayHello()); } } - Входные данные:java
// Не требуется
- Решение:
Создание модуля с библиотекой: Создайте модуль
math.module, который содержит классMathUtilsс методомadd(int a, int b).- Решение:java
// math.module/src/MathUtils.java module math.module { } public class MathUtils { public int add(int a, int b) { return a + b; } } - Входные данные:java
// Не требуется
- Решение:
Использование утилитарного модуля: Создайте модуль
app.module, который используетMathUtilsизmath.module.- Решение:java
// app.module/src/App.java module app.module { requires math.module; } import math.module.MathUtils; public class App { public static void main(String[] args) { MathUtils utils = new MathUtils(); System.out.println("Sum: " + utils.add(5, 10)); } } - Входные данные:java
// Не требуется
- Решение:
Создание модуля с конфигурацией: Создайте модуль
config.moduleс классомConfigдля хранения конфигурационных параметров.- Решение:java
// config.module/src/Config.java module config.module { } public class Config { public String getDbUrl() { return "jdbc:mysql://localhost:3306/mydb"; } } - Входные данные:java
// Не требуется
- Решение:
Использование конфигурационного модуля: Создайте модуль
app.module, который используетConfigизconfig.module.- Решение:java
// app.module/src/App.java module app.module { requires config.module; } import config.module.Config; public class App { public static void main(String[] args) { Config config = new Config(); System.out.println("Database URL: " + config.getDbUrl()); } } - Входные данные:java
// Не требуется
- Решение:
Создание модуля с интерфейсом: Создайте модуль
interface.moduleс интерфейсомGreetingServiceи классомEnglishGreeting.- Решение:java
// interface.module/src/GreetingService.java module interface.module { } public interface GreetingService { String greet(String name); } // interface.module/src/EnglishGreeting.java public class EnglishGreeting implements GreetingService { @Override public String greet(String name) { return "Hello, " + name; } } - Входные данные:java
// Не требуется
- Решение:
Использование интерфейса: Создайте модуль
app.module, который используетGreetingServiceизinterface.module.- Решение:java
// app.module/src/App.java module app.module { requires interface.module; } import interface.module.GreetingService; import interface.module.EnglishGreeting; public class App { public static void main(String[] args) { GreetingService greeting = new EnglishGreeting(); System.out.println(greeting.greet("Alice")); } } - Входные данные:java
// Не требуется
- Решение:
Создание модуля с зависимостями: Создайте модуль
utils.module, который содержит классStringUtilsс методомtoUpperCase(String str).- Решение:java
// utils.module/src/StringUtils.java module utils.module { } public class StringUtils { public String toUpperCase(String str) { return str.toUpperCase(); } } - Входные данные:java
// Не требуется
- Решение:
Использование модуля с зависимостями: Создайте модуль
app.module, который используетStringUtilsизutils.module.- Решение:java
// app.module/src/App.java module app.module { requires utils.module; } import utils.module.StringUtils; public class App { public static void main(String[] args) { StringUtils utils = new StringUtils(); System.out.println("Uppercase: " + utils.toUpperCase("hello")); } } - Входные данные:java
// Не требуется
- Решение:
Создание модуля с коллекциями: Создайте модуль
collection.module, который содержит классCollectionUtilsс методом для получения размера списка.- Решение:java
// collection.module/src/CollectionUtils.java module collection.module { } import java.util.List; public class CollectionUtils { public int getSize(List<?> list) { return list.size(); } } - Входные данные:java
// Не требуется
- Решение:
Использование модуля коллекций: Создайте модуль
app.module, который используетCollectionUtilsизcollection.module.- Решение:java
// app.module/src/App.java module app.module { requires collection.module; } import collection.module.CollectionUtils; import java.util.Arrays; public class App { public static void main(String[] args) { CollectionUtils utils = new CollectionUtils(); System.out.println("Size: " + utils.getSize(Arrays.asList(1, 2, 3))); } } - Входные данные:java
// Не требуется
- Решение:
Создание модуля с конфигурацией: Создайте модуль
settings.module, который содержит классSettingsс конфигурационными параметрами.- Решение:java
// settings.module/src/Settings.java module settings.module { } public class Settings { public String getApplicationName() { return "My Application"; } } - Входные данные:java
// Не требуется
- Решение:
Использование конфигурационного модуля: Создайте модуль
app.module, который используетSettingsизsettings.module.- Решение:java
// app.module/src/App.java module app.module { requires settings.module; } import settings.module.Settings; public class App { public static void main(String[] args) { Settings settings = new Settings(); System.out.println("Application Name: " + settings.getApplicationName()); } } - Входные данные:java
// Не требуется
- Решение:
Создание модуля с потоками: Создайте модуль
thread.moduleс классомThreadUtilsдля работы с потоками.- Решение:java
// thread.module/src/ThreadUtils.java module thread.module { } public class ThreadUtils { public void runThread(Runnable runnable) { new Thread(runnable).start(); } } - Входные данные:java
// Не требуется
- Решение:
Использование модуля потоков: Создайте модуль
app.module, который используетThreadUtilsизthread.module.- Решение:java
// app.module/src/App.java module app.module { requires thread.module; } import thread.module.ThreadUtils; public class App { public static void main(String[] args) { ThreadUtils threadUtils = new ThreadUtils(); threadUtils.runThread(() -> System.out.println("Thread is running!")); } } - Входные данные:java
// Не требуется
- Решение:
Создание модуля с обработкой исключений: Создайте модуль
exception.moduleс классомExceptionUtilsдля работы с исключениями.- Решение:java
// exception.module/src/ExceptionUtils.java module exception.module { } public class ExceptionUtils { public void throwException() throws Exception { throw new Exception("This is a custom exception!"); } } - Входные данные:java
// Не требуется
- Решение:
Использование модуля исключений: Создайте модуль
app.module, который используетExceptionUtilsизexception.module.- Решение:java
// app.module/src/App.java module app.module { requires exception.module; } import exception.module.ExceptionUtils; public class App { public static void main(String[] args) { ExceptionUtils exceptionUtils = new ExceptionUtils(); try { exceptionUtils.throwException(); } catch (Exception e) { System.out.println("Caught: " + e.getMessage()); } } } - Входные данные:java
// Не требуется
- Решение:
Создание модуля для сериализации: Создайте модуль
serialization.moduleс классомSerializablePerson.- Решение:java
// serialization.module/src/SerializablePerson.java module serialization.module { } import java.io.Serializable; public class SerializablePerson implements Serializable { private String name; public SerializablePerson(String name) { this.name = name; } public String getName() { return name; } } - Входные данные:java
// Не требуется
- Решение:
Использование модуля сериализации: Создайте модуль
app.module, который используетSerializablePersonизserialization.module.- Решение:java
// app.module/src/App.java module app.module { requires serialization.module; } import serialization.module.SerializablePerson; public class App { public static void main(String[] args) { SerializablePerson person = new SerializablePerson("John"); System.out.println("Person Name: " + person.getName()); } } - Входные данные:java
// Не требуется
- Решение:
Сложные задачи
Создание модуля с зависимостями: Создайте модуль
data.module, который содержит классDataLoaderдля загрузки данных из файла.- Решение:java
// data.module/src/DataLoader.java module data.module { } import java.io.BufferedReader; import java.io.FileReader; import java.io.IOException; import java.util.ArrayList; import java.util.List; public class DataLoader { public List<String> loadData(String filePath) throws IOException { List<String> data = new ArrayList<>(); try (BufferedReader br = new BufferedReader(new FileReader(filePath))) { String line; while ((line = br.readLine()) != null) { data.add(line); } } return data; } } - Входные данные:java
// Путь к файлу: "data.txt"
- Решение:
Использование модуля загрузки данных: Создайте модуль
app.module, который используетDataLoaderизdata.module.- Решение:java
// app.module/src/App.java module app.module { requires data.module; } import data.module.DataLoader; public class App { public static void main(String[] args) { DataLoader loader = new DataLoader(); try { loader.loadData("data.txt").forEach(System.out::println); } catch (IOException e) { e.printStackTrace(); } } } - Входные данные:java
// Путь к файлу: "data.txt"
- Решение:
Создание модуля для обработки исключений: Создайте модуль
error.moduleс классомErrorHandler, который обрабатывает исключения.- Решение:java
// error.module/src/ErrorHandler.java module error.module { } public class ErrorHandler { public void handleError(Exception e) { System.out.println("Error occurred: " + e.getMessage()); } } - Входные данные:java
// Не требуется
- Решение:
Использование модуля обработки ошибок: Создайте модуль
app.module, который используетErrorHandlerизerror.module.- Решение:java
// app.module/src/App.java module app.module { requires error.module; } import error.module.ErrorHandler; public class App { public static void main(String[] args) { ErrorHandler handler = new ErrorHandler(); try { throw new Exception("This is an exception."); } catch (Exception e) { handler.handleError(e); } } } - Входные данные:java
// Не требуется
- Решение:
Создание модуля для обработки JSON: Создайте модуль
json.moduleс классомJsonParserдля парсинга JSON.- Решение:java
// json.module/src/JsonParser.java module json.module { } import org.json.JSONObject; public class JsonParser { public String parse(String json) { JSONObject jsonObject = new JSONObject(json); return jsonObject.toString(4); // Форматированный вывод } } - Входные данные:java
// JSON: {"name": "Alice", "age": 25}
- Решение:
Использование модуля парсинга JSON: Создайте модуль
app.module, который используетJsonParserизjson.module.- Решение:java
// app.module/src/App.java module app.module { requires json.module; requires org.json; // добавьте эту зависимость в модуль } import json.module.JsonParser; public class App { public static void main(String[] args) { JsonParser parser = new JsonParser(); String json = "{\"name\": \"Alice\", \"age\": 25}"; System.out.println(parser.parse(json)); } } - Входные данные:java
// JSON: {"name": "Alice", "age": 25}
- Решение:
Создание модуля для работы с API: Создайте модуль
api.moduleс классомApiClientдля работы с HTTP-запросами.- Решение:java
// api.module/src/ApiClient.java module api.module { } import java.io.BufferedReader; import java.io.InputStreamReader; import java.net.HttpURLConnection; import java.net.URL; public class ApiClient { public String get(String urlString) throws Exception { URL url = new URL(urlString); HttpURLConnection conn = (HttpURLConnection) url.openConnection(); conn.setRequestMethod("GET"); try (BufferedReader in = new BufferedReader(new InputStreamReader(conn.getInputStream()))) { StringBuilder response = new StringBuilder(); String inputLine; while ((inputLine = in.readLine()) != null) { response.append(inputLine); } return response.toString(); } } } - Входные данные:java
// URL: "https://api.example.com/data"
- Решение:
Использование модуля API-клиента: Создайте модуль
app.module, который используетApiClientизapi.module.- Решение:java
// app.module/src/App.java module app.module { requires api.module; } import api.module.ApiClient; public class App { public static void main(String[] args) { ApiClient client = new ApiClient(); try { String response = client.get("https://api.example.com/data"); System.out.println("Response: " + response); } catch (Exception e) { e.printStackTrace(); } } } - Входные данные:java
// URL: "https://api.example.com/data"
- Решение:
Создание модуля для работы с базами данных: Создайте модуль
database.moduleс классомDatabaseConnectorдля подключения к базе данных.- Решение:java
// database.module/src/DatabaseConnector.java module database.module { } import java.sql.Connection; import java.sql.DriverManager; import java.sql.SQLException; public class DatabaseConnector { public Connection connect(String url, String user, String password) throws SQLException { return DriverManager.getConnection(url, user, password); } } - Входные данные:java
// URL: "jdbc:mysql://localhost:3306/mydb", User: "root", Password: "password"
- Решение:
Использование модуля базы данных: Создайте модуль
app.module, который используетDatabaseConnectorизdatabase.module.- Решение:java
// app.module/src/App.java module app.module { requires database.module; } import database.module.DatabaseConnector; public class App { public static void main(String[] args) { DatabaseConnector connector = new DatabaseConnector(); try { connector.connect("jdbc:mysql://localhost:3306/mydb", "root", "password"); System.out.println("Connected to the database successfully!"); } catch (SQLException e) { e.printStackTrace(); } } } - Входные данные:java
// URL: "jdbc:mysql://localhost:3306/mydb", User: "root", Password: "password"
- Решение:
МАТЕМАТИЧЕСКИЕ ВЫЧИСЛЕНИЯ И КЛАСС MATH
Базовые задачи
Нахождение квадратного корня: Напишите программу, которая находит квадратный корень числа, введенного пользователем.
- Решение:java
import java.util.Scanner; public class SquareRootCalculator { public static void main(String[] args) { Scanner scanner = new Scanner(System.in); System.out.print("Введите число: "); double number = scanner.nextDouble(); System.out.println("Квадратный корень: " + Math.sqrt(number)); } } - Входные данные:
25
- Решение:
Вычисление степени: Напишите программу, которая возводит число в степень.
- Решение:java
import java.util.Scanner; public class PowerCalculator { public static void main(String[] args) { Scanner scanner = new Scanner(System.in); System.out.print("Введите число: "); double base = scanner.nextDouble(); System.out.print("Введите степень: "); double exponent = scanner.nextDouble(); System.out.println("Результат: " + Math.pow(base, exponent)); } } - Входные данные:
2,3
- Решение:
Нахождение синуса угла: Напишите программу для вычисления синуса угла, введенного пользователем в градусах.
- Решение:java
import java.util.Scanner; public class SineCalculator { public static void main(String[] args) { Scanner scanner = new Scanner(System.in); System.out.print("Введите угол в градусах: "); double degrees = scanner.nextDouble(); double radians = Math.toRadians(degrees); System.out.println("Синус: " + Math.sin(radians)); } } - Входные данные:
30
- Решение:
Генерация случайного числа: Напишите программу, которая генерирует случайное число от 1 до 100.
- Решение:java
public class RandomNumberGenerator { public static void main(String[] args) { int randomNumber = (int) (Math.random() * 100) + 1; System.out.println("Случайное число: " + randomNumber); } } - Входные данные:
не требуется
- Решение:
Наибольшее из двух чисел: Напишите программу, которая находит наибольшее из двух введенных чисел.
- Решение:java
import java.util.Scanner; public class MaxOfTwoNumbers { public static void main(String[] args) { Scanner scanner = new Scanner(System.in); System.out.print("Введите первое число: "); double num1 = scanner.nextDouble(); System.out.print("Введите второе число: "); double num2 = scanner.nextDouble(); System.out.println("Наибольшее число: " + Math.max(num1, num2)); } } - Входные данные:
5,10
- Решение:
Нахождение абсолютного значения: Напишите программу, которая находит абсолютное значение числа.
- Решение:java
import java.util.Scanner; public class AbsoluteValueCalculator { public static void main(String[] args) { Scanner scanner = new Scanner(System.in); System.out.print("Введите число: "); double number = scanner.nextDouble(); System.out.println("Абсолютное значение: " + Math.abs(number)); } } - Входные данные:
-42.5
- Решение:
Нахождение косинуса угла: Напишите программу для вычисления косинуса угла, введенного пользователем в градусах.
- Решение:java
import java.util.Scanner; public class CosineCalculator { public static void main(String[] args) { Scanner scanner = new Scanner(System.in); System.out.print("Введите угол в градусах: "); double degrees = scanner.nextDouble(); double radians = Math.toRadians(degrees); System.out.println("Косинус: " + Math.cos(radians)); } } - Входные данные:
60
- Решение:
Нахождение тангенса угла: Напишите программу для вычисления тангенса угла, введенного пользователем в градусах.
- Решение:java
import java.util.Scanner; public class TangentCalculator { public static void main(String[] args) { Scanner scanner = new Scanner(System.in); System.out.print("Введите угол в градусах: "); double degrees = scanner.nextDouble(); double radians = Math.toRadians(degrees); System.out.println("Тангенс: " + Math.tan(radians)); } } - Входные данные:
45
- Решение:
Выбор наименьшего числа: Напишите программу, которая находит наименьшее из трех введенных чисел.
- Решение:java
import java.util.Scanner; public class MinOfThreeNumbers { public static void main(String[] args) { Scanner scanner = new Scanner(System.in); System.out.print("Введите первое число: "); double num1 = scanner.nextDouble(); System.out.print("Введите второе число: "); double num2 = scanner.nextDouble(); System.out.print("Введите третье число: "); double num3 = scanner.nextDouble(); System.out.println("Наименьшее число: " + Math.min(Math.min(num1, num2), num3)); } } - Входные данные:
3,5,1
- Решение:
Генерация случайного числа в диапазоне: Напишите программу, которая генерирует случайное число в заданном диапазоне.
- Решение:java
import java.util.Scanner; public class RandomInRange { public static void main(String[] args) { Scanner scanner = new Scanner(System.in); System.out.print("Введите нижний предел: "); int lower = scanner.nextInt(); System.out.print("Введите верхний предел: "); int upper = scanner.nextInt(); int randomNumber = lower + (int) (Math.random() * (upper - lower + 1)); System.out.println("Случайное число: " + randomNumber); } } - Входные данные:
10,50
- Определение расстояния между двумя точками: Напишите программу, которая находит расстояние между двумя точками на плоскости.
- Решение:java
import java.util.Scanner; public class DistanceCalculator { public static void main(String[] args) { Scanner scanner = new Scanner(System.in); System.out.print("Введите x1: "); double x1 = scanner.nextDouble(); System.out.print("Введите y1: "); double y1 = scanner.nextDouble(); System.out.print("Введите x2: "); double x2 = scanner.nextDouble(); System.out.print("Введите y2: "); double y2 = scanner.nextDouble(); double distance = Math.sqrt(Math.pow(x2 - x1, 2) + Math.pow(y2 - y1, 2)); System.out.println("Расстояние: " + distance); } } - Входные данные:
0,0,3,4
- Проверка, является ли число четным: Напишите программу, которая проверяет, является ли введенное число четным.
- Решение:java
import java.util.Scanner; public class EvenOddChecker { public static void main(String[] args) { Scanner scanner = new Scanner(System.in); System.out.print("Введите число: "); int number = scanner.nextInt(); if (number % 2 == 0) { System.out.println("Четное число"); } else { System.out.println("Нечетное число"); } } } - Входные данные:
8
- Нахождение факторала числа: Напишите программу для нахождения факториала числа.
- Решение:java
import java.util.Scanner; public class FactorialCalculator { public static void main(String[] args) { Scanner scanner = new Scanner(System.in); System.out.print("Введите число: "); int number = scanner.nextInt(); long factorial = 1; for (int i = 1; i <= number; i++) { factorial *= i; } System.out.println("Факториал: " + factorial); } } - Входные данные:
5
- Нахождение среднего арифметического: Напишите программу для нахождения среднего арифметического из нескольких чисел.
- Решение:java
import java.util.Scanner; public class AverageCalculator { public static void main(String[] args) { Scanner scanner = new Scanner(System.in); System.out.print("Введите количество чисел: "); int count = scanner.nextInt(); double sum = 0; for (int i = 0; i < count; i++) { System.out.print("Введите число " + (i + 1) + ": "); sum += scanner.nextDouble(); } System.out.println("Среднее арифметическое: " + (sum / count)); } } - Входные данные:
3,4,5,6
- Проверка, является ли число простым: Напишите программу для проверки, является ли введенное число простым.
- Решение:java
import java.util.Scanner; public class PrimeChecker { public static void main(String[] args) { Scanner scanner = new Scanner(System.in); System.out.print("Введите число: "); int number = scanner.nextInt(); boolean isPrime = true; if (number <= 1) { isPrime = false; } else { for (int i = 2; i <= Math.sqrt(number); i++) { if (number % i == 0) { isPrime = false; break; } } } System.out.println(isPrime ? "Число простое" : "Число не является простым"); } } - Входные данные:
17
- Перевод градусов в радианы: Напишите программу для перевода угла из градусов в радианы.
- Решение:java
import java.util.Scanner; public class DegreesToRadians { public static void main(String[] args) { Scanner scanner = new Scanner(System.in); System.out.print("Введите угол в градусах: "); double degrees = scanner.nextDouble(); double radians = Math.toRadians(degrees); System.out.println("Угол в радианах: " + radians); } } - Входные данные:
180
- Нахождение логарифма: Напишите программу для нахождения логарифма числа по основанию 10.
- Решение:java
import java.util.Scanner; public class LogarithmCalculator { public static void main(String[] args) { Scanner scanner = new Scanner(System.in); System.out.print("Введите число: "); double number = scanner.nextDouble(); System.out.println("Логарифм: " + Math.log10(number)); } } - Входные данные:
100
- Нахождение модуля числа: Напишите программу для нахождения модуля числа.
- Решение:java
import java.util.Scanner; public class ModulusCalculator { public static void main(String[] args) { Scanner scanner = new Scanner(System.in); System.out.print("Введите число: "); double number = scanner.nextDouble(); System.out.println("Модуль числа: " + Math.abs(number)); } } - Входные данные:
-12.34
- Вычисление среднеквадратичного отклонения: Напишите программу, вычисляющую среднеквадратичное отклонение набора чисел.
- Решение:java
import java.util.Scanner; public class StandardDeviationCalculator { public static void main(String[] args) { Scanner scanner = new Scanner(System.in); System.out.print("Введите количество чисел: "); int count = scanner.nextInt(); double[] numbers = new double[count]; double sum = 0; for (int i = 0; i < count; i++) { System.out.print("Введите число " + (i + 1) + ": "); numbers[i] = scanner.nextDouble(); sum += numbers[i]; } double mean = sum / count; double sumOfSquares = 0; for (double num : numbers) { sumOfSquares += Math.pow(num - mean, 2); } double standardDeviation = Math.sqrt(sumOfSquares / count); System.out.println("Среднеквадратичное отклонение: " + standardDeviation); } } - Входные данные:
5,2,4,6,8
- Вычисление периметра и площади круга: Напишите программу для вычисления периметра и площади круга по радиусу.
- Решение:java
import java.util.Scanner; public class CircleCalculator { public static void main(String[] args) { Scanner scanner = new Scanner(System.in); System.out.print("Введите радиус круга: "); double radius = scanner.nextDouble(); double perimeter = 2 * Math.PI * radius; double area = Math.PI * Math.pow(radius, 2); System.out.println("Периметр круга: " + perimeter); System.out.println("Площадь круга: " + area); } } - Входные данные:
5
Сложные задачи
Вычисление чисел Фибоначчи: Напишите программу, которая вычисляет n-ое число Фибоначчи.
- Решение:java
import java.util.Scanner; public class FibonacciCalculator { public static void main(String[] args) { Scanner scanner = new Scanner(System.in); System.out.print("Введите номер числа Фибоначчи: "); int n = scanner.nextInt(); System.out.println("Число Фибоначчи: " + fibonacci(n)); } public static int fibonacci(int n) { if (n <= 1) { return n; } return fibonacci(n - 1) + fibonacci(n - 2); } } - Входные данные:
6
- Решение:
Нахождение максимального общего делителя (НОД): Напишите программу для нахождения НОД двух чисел.
- Решение:java
import java.util.Scanner; public class GCDCalculator { public static void main(String[] args) { Scanner scanner = new Scanner(System.in); System.out.print("Введите первое число: "); int a = scanner.nextInt(); System.out.print("Введите второе число: "); int b = scanner.nextInt(); System.out.println("НОД: " + gcd(a, b)); } public static int gcd(int a, int b) { if (b == 0) { return a; } return gcd(b, a % b); } } - Входные данные:
48,18
- Решение:
Вычисление факториала с использованием BigInteger: Напишите программу, которая вычисляет факториал числа с использованием BigInteger.
- Решение:java
import java.math.BigInteger; import java.util.Scanner; public class BigIntegerFactorial { public static void main(String[] args) { Scanner scanner = new Scanner(System.in); System.out.print("Введите число: "); int n = scanner.nextInt(); System.out.println("Факториал: " + factorial(n)); } public static BigInteger factorial(int n) { BigInteger result = BigInteger.ONE; for (int i = 2; i <= n; i++) { result = result.multiply(BigInteger.valueOf(i)); } return result; } } - Входные данные:
20
- Решение:
Проверка на простое число с помощью BigInteger: Напишите программу для проверки, является ли число простым, используя класс BigInteger.
- Решение:java
import java.math.BigInteger; import java.util.Scanner; public class PrimeCheckerBigInteger { public static void main(String[] args) { Scanner scanner = new Scanner(System.in); System.out.print("Введите число: "); BigInteger number = scanner.nextBigInteger(); System.out.println("Число простое: " + number.isProbablePrime(1)); } } - Входные данные:
19
- Решение:
Вычисление площади треугольника по трем сторонам: Напишите программу, которая вычисляет площадь треугольника по длинам его сторон, используя формулу Герона.
- Решение:java
import java.util.Scanner; public class TriangleArea { public static void main(String[] args) { Scanner scanner = new Scanner(System.in); System.out.print("Введите длину первой стороны: "); double a = scanner.nextDouble(); System.out.print("Введите длину второй стороны: "); double b = scanner.nextDouble(); System.out.print("Введите длину третьей стороны: "); double c = scanner.nextDouble(); double s = (a + b + c) / 2; double area = Math.sqrt(s * (s - a) * (s - b) * (s - c)); System.out.println("Площадь треугольника: " + area); } } - Входные данные:
3,4,5
- Решение:
Вычисление среднего арифметического с использованием BigDecimal: Напишите программу для нахождения среднего арифметического с использованием BigDecimal.
- Решение:java
import java.math.BigDecimal; import java.util.Scanner; public class AverageWithBigDecimal { public static void main(String[] args) { Scanner scanner = new Scanner(System.in); System.out.print("Введите количество чисел: "); int count = scanner.nextInt(); BigDecimal sum = BigDecimal.ZERO; for (int i = 0; i < count; i++) { System.out.print("Введите число " + (i + 1) + ": "); sum = sum.add(scanner.nextBigDecimal()); } BigDecimal average = sum.divide(BigDecimal.valueOf(count)); System.out.println("Среднее арифметическое: " + average); } } - Входные данные:
3,4.5,5.5,6.5
- Решение:
Преобразование целого числа в строку с помощью String.valueOf(): Напишите программу, которая преобразует целое число в строку.
- Решение:java
import java.util.Scanner; public class IntToStringConverter { public static void main(String[] args) { Scanner scanner = new Scanner(System.in); System.out.print("Введите целое число: "); int number = scanner.nextInt(); String str = String.valueOf(number); System.out.println("Строка: " + str); } } - Входные данные:
123
- Решение:
Вывод чисел от 1 до N с использованием цикла for: Напишите программу, которая выводит числа от 1 до N.
- Решение:java
import java.util.Scanner; public class NumbersFromOneToN { public static void main(String[] args) { Scanner scanner = new Scanner(System.in); System.out.print("Введите число N: "); int n = scanner.nextInt(); for (int i = 1; i <= n; i++) { System.out.print(i + " "); } } } - Входные данные:
5
- Решение:
Нахождение наибольшего числа в массиве: Напишите программу, которая находит наибольшее число в массиве.
- Решение:java
import java.util.Scanner; public class MaxInArray { public static void main(String[] args) { Scanner scanner = new Scanner(System.in); System.out.print("Введите количество элементов в массиве: "); int n = scanner.nextInt(); int[] array = new int[n]; for (int i = 0; i < n; i++) { System.out.print("Введите элемент " + (i + 1) + ": "); array[i] = scanner.nextInt(); } int max = array[0]; for (int i = 1; i < n; i++) { if (array[i] > max) { max = array[i]; } } System.out.println("Наибольшее число в массиве: " + max); } } - Входные данные:
5,1,3,7,2,6
- Решение:
Перевод радиан в градусы: Напишите программу для перевода угла из радиан в градусы.
- Решение:java
import java.util.Scanner; public class RadiansToDegrees { public static void main(String[] args) { Scanner scanner = new Scanner(System.in); System.out.print("Введите угол в радианах: "); double radians = scanner.nextDouble(); double degrees = Math.toDegrees(radians); System.out.println("Угол в градусах: " + degrees); } } - Входные данные:
1.57
БОЛЬШИЕ ЧИСЛА BIGINTEGER И BIGDECIMAL
Базовые задачи
Сложение двух больших чисел: Напишите программу, которая складывает два больших числа.
- Решение:java
import java.math.BigInteger; import java.util.Scanner; public class BigIntegerAddition { public static void main(String[] args) { Scanner scanner = new Scanner(System.in); System.out.print("Введите первое большое число: "); BigInteger num1 = scanner.nextBigInteger(); System.out.print("Введите второе большое число: "); BigInteger num2 = scanner.nextBigInteger(); System.out.println("Сумма: " + num1.add(num2)); } } - Входные данные:
12345678901234567890,98765432109876543210
- Решение:
Вычитание двух больших чисел: Напишите программу, которая вычитает одно большое число из другого.
- Решение:java
import java.math.BigInteger; import java.util.Scanner; public class BigIntegerSubtraction { public static void main(String[] args) { Scanner scanner = new Scanner(System.in); System.out.print("Введите первое большое число: "); BigInteger num1 = scanner.nextBigInteger(); System.out.print("Введите второе большое число: "); BigInteger num2 = scanner.nextBigInteger(); System.out.println("Разность: " + num1.subtract(num2)); } } - Входные данные:
10000000000000000000,9999999999999999999
- Решение:
Умножение двух больших чисел: Напишите программу, которая умножает два больших числа.
- Решение:java
import java.math.BigInteger; import java.util.Scanner; public class BigIntegerMultiplication { public static void main(String[] args) { Scanner scanner = new Scanner(System.in); System.out.print("Введите первое большое число: "); BigInteger num1 = scanner.nextBigInteger(); System.out.print("Введите второе большое число: "); BigInteger num2 = scanner.nextBigInteger(); System.out.println("Произведение: " + num1.multiply(num2)); } } - Входные данные:
12345678901234567890,2
- Решение:
Деление двух больших чисел: Напишите программу, которая делит одно большое число на другое.
- Решение:java
import java.math.BigInteger; import java.util.Scanner; public class BigIntegerDivision { public static void main(String[] args) { Scanner scanner = new Scanner(System.in); System.out.print("Введите делимое: "); BigInteger num1 = scanner.nextBigInteger(); System.out.print("Введите делитель: "); BigInteger num2 = scanner.nextBigInteger(); System.out.println("Частное: " + num1.divide(num2)); } } - Входные данные:
10000000000000000000,2
- Решение:
Вычисление остатка от деления двух больших чисел: Напишите программу для нахождения остатка от деления двух больших чисел.
- Решение:java
import java.math.BigInteger; import java.util.Scanner; public class BigIntegerRemainder { public static void main(String[] args) { Scanner scanner = new Scanner(System.in); System.out.print("Введите делимое: "); BigInteger num1 = scanner.nextBigInteger(); System.out.print("Введите делитель: "); BigInteger num2 = scanner.nextBigInteger(); System.out.println("Остаток: " + num1.remainder(num2)); } } - Входные данные:
100,3
- Решение:
Сравнение двух больших чисел: Напишите программу, которая сравнивает два больших числа.
- Решение:java
import java.math.BigInteger; import java.util.Scanner; public class BigIntegerComparison { public static void main(String[] args) { Scanner scanner = new Scanner(System.in); System.out.print("Введите первое большое число: "); BigInteger num1 = scanner.nextBigInteger(); System.out.print("Введите второе большое число: "); BigInteger num2 = scanner.nextBigInteger(); if (num1.equals(num2)) { System.out.println("Числа равны"); } else if (num1.compareTo(num2) > 0) { System.out.println("Первое число больше второго"); } else { System.out.println("Второе число больше первого"); } } } - Входные данные:
12345678901234567890,12345678901234567891
- Решение:
Возведение в степень с использованием BigInteger: Напишите программу для возведения большого числа в степень.
- Решение:java
import java.math.BigInteger; import java.util.Scanner; public class BigIntegerExponentiation { public static void main(String[] args) { Scanner scanner = new Scanner(System.in); System.out.print("Введите большое число: "); BigInteger base = scanner.nextBigInteger(); System.out.print("Введите степень: "); int exponent = scanner.nextInt(); System.out.println("Результат: " + base.pow(exponent)); } } - Входные данные:
2,10
- Решение:
Сложение двух больших десятичных чисел: Напишите программу для сложения двух чисел с плавающей запятой с использованием BigDecimal.
- Решение:java
import java.math.BigDecimal; import java.util.Scanner; public class BigDecimalAddition { public static void main(String[] args) { Scanner scanner = new Scanner(System.in); System.out.print("Введите первое число: "); BigDecimal num1 = scanner.nextBigDecimal(); System.out.print("Введите второе число: "); BigDecimal num2 = scanner.nextBigDecimal(); System.out.println("Сумма: " + num1.add(num2)); } } - Входные данные:
12345.678,98765.432
- Решение:
Вычитание двух больших десятичных чисел: Напишите программу для вычитания одного большого числа с плавающей запятой из другого.
- Решение:java
import java.math.BigDecimal; import java.util.Scanner; public class BigDecimalSubtraction { public static void main(String[] args) { Scanner scanner = new Scanner(System.in); System.out.print("Введите первое число: "); BigDecimal num1 = scanner.nextBigDecimal(); System.out.print("Введите второе число: "); BigDecimal num2 = scanner.nextBigDecimal(); System.out.println("Разность: " + num1.subtract(num2)); } } - Входные данные:
1000.50,500.25
- Решение:
Умножение двух больших десятичных чисел: Напишите программу для умножения двух чисел с плавающей запятой с использованием BigDecimal.
- Решение:java
import java.math.BigDecimal; import java.util.Scanner; public class BigDecimalMultiplication { public static void main(String[] args) { Scanner scanner = new Scanner(System.in); System.out.print("Введите первое число: "); BigDecimal num1 = scanner.nextBigDecimal(); System.out.print("Введите второе число: "); BigDecimal num2 = scanner.nextBigDecimal(); System.out.println("Произведение: " + num1.multiply(num2)); } } - Входные данные:
3.14,2.0
Примечания
- BigInteger и BigDecimal обеспечивают возможность работы с числами, превышающими стандартные типы данных в Java.
- Для работы с большими числами рекомендуется использовать класс BigInteger для целых чисел и класс BigDecimal для дробных чисел.
- Обязательно учитывайте возможные исключения и проверяйте ввод пользователя для более надежных программ.
JAVAFX
Базовые задачи
Создание простого приложения JavaFX: Напишите приложение, которое отображает "Hello, JavaFX!" на экране.
- Решение:java
import javafx.application.Application; import javafx.scene.Scene; import javafx.scene.control.Label; import javafx.stage.Stage; public class HelloJavaFX extends Application { @Override public void start(Stage primaryStage) { Label label = new Label("Hello, JavaFX!"); Scene scene = new Scene(label, 300, 200); primaryStage.setScene(scene); primaryStage.setTitle("Hello JavaFX"); primaryStage.show(); } public static void main(String[] args) { launch(args); } } - Входные данные: нет
- Решение:
Изменение заголовка окна: Создайте приложение, которое позволяет пользователю ввести текст для изменения заголовка окна.
- Решение:java
import javafx.application.Application; import javafx.scene.Scene; import javafx.scene.control.Button; import javafx.scene.control.TextField; import javafx.scene.layout.VBox; import javafx.stage.Stage; public class ChangeTitle extends Application { @Override public void start(Stage primaryStage) { TextField textField = new TextField("Введите заголовок"); Button button = new Button("Изменить заголовок"); button.setOnAction(e -> primaryStage.setTitle(textField.getText())); VBox vbox = new VBox(textField, button); Scene scene = new Scene(vbox, 300, 200); primaryStage.setScene(scene); primaryStage.show(); } public static void main(String[] args) { launch(args); } } - Входные данные: текст в текстовом поле
- Решение:
Изменение размера окна: Напишите приложение, которое позволяет пользователю ввести ширину и высоту окна, и после нажатия кнопки размер окна изменится.
- Решение:java
import javafx.application.Application; import javafx.scene.Scene; import javafx.scene.control.Button; import javafx.scene.control.TextField; import javafx.scene.layout.VBox; import javafx.stage.Stage; public class ResizeWindow extends Application { @Override public void start(Stage primaryStage) { TextField widthField = new TextField("Ширина"); TextField heightField = new TextField("Высота"); Button button = new Button("Изменить размер"); button.setOnAction(e -> { double width = Double.parseDouble(widthField.getText()); double height = Double.parseDouble(heightField.getText()); primaryStage.setWidth(width); primaryStage.setHeight(height); }); VBox vbox = new VBox(widthField, heightField, button); Scene scene = new Scene(vbox, 300, 200); primaryStage.setScene(scene); primaryStage.show(); } public static void main(String[] args) { launch(args); } } - Входные данные: ширина и высота окна
- Решение:
Создание кнопки с обработчиком событий: Напишите приложение, которое отображает кнопку, и при нажатии на нее выводит сообщение в консоль.
- Решение:java
import javafx.application.Application; import javafx.scene.Scene; import javafx.scene.control.Button; import javafx.scene.layout.StackPane; import javafx.stage.Stage; public class ButtonClick extends Application { @Override public void start(Stage primaryStage) { Button button = new Button("Нажми меня"); button.setOnAction(e -> System.out.println("Кнопка нажата!")); StackPane root = new StackPane(); root.getChildren().add(button); Scene scene = new Scene(root, 300, 200); primaryStage.setScene(scene); primaryStage.setTitle("Button Click Example"); primaryStage.show(); } public static void main(String[] args) { launch(args); } } - Входные данные: нет
- Решение:
Работа с текстовым полем: Создайте приложение с текстовым полем и кнопкой, при нажатии на которую содержимое текстового поля выводится в консоль.
- Решение:java
import javafx.application.Application; import javafx.scene.Scene; import javafx.scene.control.Button; import javafx.scene.control.TextField; import javafx.scene.layout.VBox; import javafx.stage.Stage; public class TextFieldExample extends Application { @Override public void start(Stage primaryStage) { TextField textField = new TextField("Введите текст"); Button button = new Button("Вывести текст"); button.setOnAction(e -> System.out.println(textField.getText())); VBox vbox = new VBox(textField, button); Scene scene = new Scene(vbox, 300, 200); primaryStage.setScene(scene); primaryStage.show(); } public static void main(String[] args) { launch(args); } } - Входные данные: текст в текстовом поле
- Решение:
Создание радиокнопок: Напишите приложение с двумя радиокнопками и кнопкой, которая показывает, какая радиокнопка выбрана.
- Решение:java
import javafx.application.Application; import javafx.scene.Scene; import javafx.scene.control.Button; import javafx.scene.control.RadioButton; import javafx.scene.control.ToggleGroup; import javafx.scene.layout.VBox; import javafx.stage.Stage; public class RadioButtonExample extends Application { @Override public void start(Stage primaryStage) { ToggleGroup group = new ToggleGroup(); RadioButton option1 = new RadioButton("Опция 1"); RadioButton option2 = new RadioButton("Опция 2"); option1.setToggleGroup(group); option2.setToggleGroup(group); Button button = new Button("Показать выбранную опцию"); button.setOnAction(e -> { RadioButton selected = (RadioButton) group.getSelectedToggle(); if (selected != null) { System.out.println("Выбрана: " + selected.getText()); } }); VBox vbox = new VBox(option1, option2, button); Scene scene = new Scene(vbox, 300, 200); primaryStage.setScene(scene); primaryStage.show(); } public static void main(String[] args) { launch(args); } } - Входные данные: выбор радиокнопки
- Решение:
Создание выпадающего списка: Напишите приложение с выпадающим списком и кнопкой, которая показывает выбранный элемент.
- Решение:java
import javafx.application.Application; import javafx.scene.Scene; import javafx.scene.control.Button; import javafx.scene.control.ComboBox; import javafx.scene.layout.VBox; import javafx.stage.Stage; public class ComboBoxExample extends Application { @Override public void start(Stage primaryStage) { ComboBox<String> comboBox = new ComboBox<>(); comboBox.getItems().addAll("Первый", "Второй", "Третий"); Button button = new Button("Показать выбранный элемент"); button.setOnAction(e -> System.out.println("Выбрано: " + comboBox.getValue())); VBox vbox = new VBox(comboBox, button); Scene scene = new Scene(vbox, 300, 200); primaryStage.setScene(scene); primaryStage.show(); } public static void main(String[] args) { launch(args); } } - Входные данные: выбор элемента из выпадающего списка
- Решение:
Создание простой таблицы: Напишите приложение, которое отображает простую таблицу с данными.
- Решение:java
import javafx.application.Application; import javafx.scene.Scene; import javafx.scene.control.TableColumn; import javafx.scene.control.TableView; import javafx.scene.control.cell.PropertyValueFactory; import javafx.scene.layout.VBox; import javafx.stage.Stage; public class TableViewExample extends Application { public static class Person { private final String name; private final int age; public Person(String name, int age) { this.name = name; this.age = age; } public String getName() { return name; } public int getAge() { return age; } } @Override public void start(Stage primaryStage) { TableView<Person> tableView = new TableView<>(); TableColumn<Person, String> nameColumn = new TableColumn<>("Имя"); nameColumn.setCellValueFactory(new PropertyValueFactory<>("name")); TableColumn<Person, Integer> ageColumn = new TableColumn<>("Возраст"); ageColumn.setCellValueFactory(new PropertyValueFactory<>("age")); tableView.getColumns().add(nameColumn); tableView.getColumns().add(ageColumn); tableView.getItems().add(new Person("Иван", 30)); tableView.getItems().add(new Person("Анна", 25)); VBox vbox = new VBox(tableView); Scene scene = new Scene(vbox, 300, 200); primaryStage.setScene(scene); primaryStage.show(); } public static void main(String[] args) { launch(args); } } - Входные данные: нет
- Решение:
Добавление изображений: Напишите приложение, которое отображает изображение.
- Решение:java
import javafx.application.Application; import javafx.scene.Scene; import javafx.scene.image.Image; import javafx.scene.image.ImageView; import javafx.scene.layout.StackPane; import javafx.stage.Stage; public class ImageExample extends Application { @Override public void start(Stage primaryStage) { Image image = new Image("file:example.jpg"); // Замените на путь к изображению ImageView imageView = new ImageView(image); StackPane root = new StackPane(imageView); Scene scene = new Scene(root, 300, 200); primaryStage.setScene(scene); primaryStage.setTitle("Изображение"); primaryStage.show(); } public static void main(String[] args) { launch(args); } } - Входные данные: путь к изображению
- Решение:
Создание простого меню: Напишите приложение с простым меню.
- Решение:java
import javafx.application.Application; import javafx.scene.Scene; import javafx.scene.control.Menu; import javafx.scene.control.MenuBar; import javafx.scene.control.MenuItem; import javafx.scene.layout.VBox; import javafx.stage.Stage; public class MenuExample extends Application { @Override public void start(Stage primaryStage) { MenuBar menuBar = new MenuBar(); Menu menu = new Menu("Файл"); MenuItem menuItem = new MenuItem("Выход"); menuItem.setOnAction(e -> System.exit(0)); menu.getItems().add(menuItem); menuBar.getMenus().add(menu); VBox vbox = new VBox(menuBar); Scene scene = new Scene(vbox, 300, 200); primaryStage.setScene(scene); primaryStage.setTitle("Простое меню"); primaryStage.show(); } public static void main(String[] args) { launch(args); } } - Входные данные: нет
- Решение:
Создание ProgressBar: Напишите приложение, которое отображает ProgressBar и обновляет его значение.
- Решение:java
import javafx.application.Application; import javafx.scene.Scene; import javafx.scene.control.Button; import javafx.scene.control.ProgressBar; import javafx.scene.layout.VBox; import javafx.stage.Stage; public class ProgressBarExample extends Application { private double progress = 0; @Override public void start(Stage primaryStage) { ProgressBar progressBar = new ProgressBar(0); Button button = new Button("Увеличить прогресс"); button.setOnAction(e -> { progress += 0.1; progressBar.setProgress(progress); }); VBox vbox = new VBox(progressBar, button); Scene scene = new Scene(vbox, 300, 200); primaryStage.setScene(scene); primaryStage.show(); } public static void main(String[] args) { launch(args); } } - Входные данные: нет
- Решение:
Создание TabPane: Напишите приложение с TabPane, содержащим несколько вкладок.
- Решение:java
import javafx.application.Application; import javafx.scene.Scene; import javafx.scene.control.Tab; import javafx.scene.control.TabPane; import javafx.scene.layout.StackPane; import javafx.stage.Stage; public class TabPaneExample extends Application { @Override public void start(Stage primaryStage) { TabPane tabPane = new TabPane(); Tab tab1 = new Tab("Вкладка 1", new StackPane()); Tab tab2 = new Tab("Вкладка 2", new StackPane()); tabPane.getTabs().add(tab1); tabPane.getTabs().add(tab2); Scene scene = new Scene(tabPane, 300, 200); primaryStage.setScene(scene); primaryStage.show(); } public static void main(String[] args) { launch(args); } } - Входные данные: нет
- Решение:
Создание Simple Alert: Напишите приложение, которое показывает предупреждающее окно при нажатии кнопки.
- Решение:java
import javafx.application.Application; import javafx.scene.Scene; import javafx.scene.control.Alert; import javafx.scene.control.Button; import javafx.scene.layout.StackPane; import javafx.stage.Stage; public class AlertExample extends Application { @Override public void start(Stage primaryStage) { Button button = new Button("Показать предупреждение"); button.setOnAction(e -> { Alert alert = new Alert(Alert.AlertType.WARNING); alert.setTitle("Предупреждение"); alert.setHeaderText(null); alert.setContentText("Это предупреждение!"); alert.showAndWait(); }); StackPane root = new StackPane(button); Scene scene = new Scene(root, 300, 200); primaryStage.setScene(scene); primaryStage.show(); } public static void main(String[] args) { launch(args); } } - Входные данные: нет
- Решение:
Сохранение и загрузка данных: Напишите приложение, которое позволяет пользователю сохранить текст в файл и загрузить его.
- Решение:java
import javafx.application.Application; import javafx.stage.FileChooser; import javafx.scene.Scene; import javafx.scene.control.Button; import javafx.scene.control.TextArea; import javafx.scene.layout.VBox; import javafx.stage.Stage; import java.io.File; import java.io.IOException; import java.nio.file.Files; public class FileExample extends Application { @Override public void start(Stage primaryStage) { TextArea textArea = new TextArea(); Button saveButton = new Button("Сохранить"); Button loadButton = new Button("Загрузить"); saveButton.setOnAction(e -> { FileChooser fileChooser = new FileChooser(); File file = fileChooser.showSaveDialog(primaryStage); if (file != null) { try { Files.write(file.toPath(), textArea.getText().getBytes()); } catch (IOException ex) { ex.printStackTrace(); } } }); loadButton.setOnAction(e -> { FileChooser fileChooser = new FileChooser(); File file = fileChooser.showOpenDialog(primaryStage); if (file != null) { try { String content = new String(Files.readAllBytes(file.toPath())); textArea.setText(content); } catch (IOException ex) { ex.printStackTrace(); } } }); VBox vbox = new VBox(textArea, saveButton, loadButton); Scene scene = new Scene(vbox, 300, 200); primaryStage.setScene(scene); primaryStage.show(); } public static void main(String[] args) { launch(args); } } - Входные данные: текст для сохранения
- Решение:
Создание Canvas: Напишите приложение, которое рисует на Canvas.
- Решение:java
import javafx.application.Application; import javafx.scene.Scene; import javafx.scene.canvas.Canvas; import javafx.scene.canvas.GraphicsContext; import javafx.scene.layout.StackPane; import javafx.stage.Stage; public class CanvasExample extends Application { @Override public void start(Stage primaryStage) { Canvas canvas = new Canvas(300, 200); GraphicsContext gc = canvas.getGraphicsContext2D(); gc.strokeRect(50, 50, 200, 100); StackPane root = new StackPane(canvas); Scene scene = new Scene(root, 300, 200); primaryStage.setScene(scene); primaryStage.show(); } public static void main(String[] args) { launch(args); } } - Входные данные: нет
- Решение:
Добавление Tooltip: Напишите приложение с элементом, к которому можно добавить подсказку (Tooltip).
- Решение:java
import javafx.application.Application; import javafx.scene.Scene; import javafx.scene.control.Button; import javafx.scene.control.Tooltip; import javafx.scene.layout.StackPane; import javafx.stage.Stage; public class TooltipExample extends Application { @Override public void start(Stage primaryStage) { Button button = new Button("Наведите курсор"); Tooltip tooltip = new Tooltip("Это подсказка!"); Tooltip.install(button, tooltip); StackPane root = new StackPane(button); Scene scene = new Scene(root, 300, 200); primaryStage.setScene(scene); primaryStage.show(); } public static void main(String[] args) { launch(args); } } - Входные данные: нет
- Решение:
Создание простого калькулятора: Напишите приложение, которое выполняет базовые арифметические операции.
- Решение:java
import javafx.application.Application; import javafx.scene.Scene; import javafx.scene.control.Button; import javafx.scene.control.TextField; import javafx.scene.layout.VBox; import javafx.stage.Stage; public class SimpleCalculator extends Application { @Override public void start(Stage primaryStage) { TextField input1 = new TextField(); TextField input2 = new TextField(); TextField result = new TextField(); result.setEditable(false); Button addButton = new Button("Сложить"); addButton.setOnAction(e -> { double num1 = Double.parseDouble(input1.getText()); double num2 = Double.parseDouble(input2.getText()); result.setText(String.valueOf(num1 + num2)); }); VBox vbox = new VBox(input1, input2, addButton, result); Scene scene = new Scene(vbox, 300, 200); primaryStage.setScene(scene); primaryStage.show(); } public static void main(String[] args) { launch(args); } } - Входные данные: два числа для сложения
- Решение:
Создание AlertDialog: Напишите приложение с кнопкой, которая вызывает AlertDialog.
- Решение:java
import javafx.application.Application; import javafx.scene.Scene; import javafx.scene.control.Alert; import javafx.scene.control.Button; import javafx.scene.layout.StackPane; import javafx.stage.Stage; public class AlertDialogExample extends Application { @Override public void start(Stage primaryStage) { Button button = new Button("Показать диалог"); button.setOnAction(e -> { Alert alert = new Alert(Alert.AlertType.INFORMATION); alert.setTitle("Информация"); alert.setHeaderText(null); alert.setContentText("Это информационное сообщение!"); alert.showAndWait(); }); StackPane root = new StackPane(button); Scene scene = new Scene(root, 300, 200); primaryStage.setScene(scene); primaryStage.show(); } public static void main(String[] args) { launch(args); } } - Входные данные: нет
- Решение:
Создание Slider: Напишите приложение с слайдером, который отображает текущее значение.
- Решение:java
import javafx.application.Application; import javafx.scene.Scene; import javafx.scene.control.Label; import javafx.scene.control.Slider; import javafx.scene.layout.VBox; import javafx.stage.Stage; public class SliderExample extends Application { @Override public void start(Stage primaryStage) { Slider slider = new Slider(0, 100, 50); Label label = new Label("Текущее значение: " + slider.getValue()); slider.valueProperty().addListener((obs, oldValue, newValue) -> label.setText("Текущее значение: " + newValue)); VBox vbox = new VBox(slider, label); Scene scene = new Scene(vbox, 300, 200); primaryStage.setScene(scene); primaryStage.show(); } public static void main(String[] args) { launch(args); } } - Входные данные: изменение значения слайдера
- Решение:
Создание FileChooser: Напишите приложение, которое позволяет пользователю выбирать файл через FileChooser.
- Решение:java
import javafx.application.Application; import javafx.stage.FileChooser; import javafx.stage.Stage; import javafx.scene.Scene; import javafx.scene.control.Button; import javafx.scene.layout.StackPane; import java.io.File; public class FileChooserExample extends Application { @Override public void start(Stage primaryStage) { Button button = new Button("Выбрать файл"); button.setOnAction(e -> { FileChooser fileChooser = new FileChooser(); File file = fileChooser.showOpenDialog(primaryStage); if (file != null) { System.out.println("Выбранный файл: " + file.getAbsolutePath()); } }); StackPane root = new StackPane(button); Scene scene = new Scene(root, 300, 200); primaryStage.setScene(scene); primaryStage.show(); } public static void main(String[] args) { launch(args); } } - Входные данные: выбор файла
- Решение:
Сложные задачи
Создание приложения с вкладками и формами: Напишите приложение с TabPane, в котором каждая вкладка содержит форму для ввода данных.
- Решение:java
import javafx.application.Application; import javafx.scene.Scene; import javafx.scene.control.Tab; import javafx.scene.control.TabPane; import javafx.scene.control.TextField; import javafx.scene.layout.VBox; import javafx.stage.Stage; public class TabbedFormExample extends Application { @Override public void start(Stage primaryStage) { TabPane tabPane = new TabPane(); Tab tab1 = new Tab("Форма 1", new VBox(new TextField("Имя"))); Tab tab2 = new Tab("Форма 2", new VBox(new TextField("Фамилия"))); tabPane.getTabs().add(tab1); tabPane.getTabs().add(tab2); Scene scene = new Scene(tabPane, 300, 200); primaryStage.setScene(scene); primaryStage.show(); } public static void main(String[] args) { launch(args); } } - Входные данные: текстовые поля для ввода
- Решение:
Создание графического редактора: Напишите приложение, которое позволяет пользователю рисовать на Canvas с использованием мыши.
- Решение:java
import javafx.application.Application; import javafx.scene.Scene; import javafx.scene.canvas.Canvas; import javafx.scene.canvas.GraphicsContext; import javafx.scene.input.MouseEvent; import javafx.scene.layout.StackPane; import javafx.stage.Stage; public class DrawingApp extends Application { @Override public void start(Stage primaryStage) { Canvas canvas = new Canvas(400, 400); GraphicsContext gc = canvas.getGraphicsContext2D(); canvas.addEventHandler(MouseEvent.MOUSE_DRAGGED, e -> { gc.fillOval(e.getX(), e.getY(), 5, 5); }); StackPane root = new StackPane(canvas); Scene scene = new Scene(root, 400, 400); primaryStage.setScene(scene); primaryStage.show(); } public static void main(String[] args) { launch(args); } } - Входные данные: движение мыши по Canvas
- Решение:
Создание простого текстового редактора: Напишите приложение, которое позволяет пользователю вводить и редактировать текст.
- Решение:java
import javafx.application.Application; import javafx.scene.Scene; import javafx.scene.control.TextArea; import javafx.scene.layout.StackPane; import javafx.stage.Stage; public class TextEditor extends Application { @Override public void start(Stage primaryStage) { TextArea textArea = new TextArea(); StackPane root = new StackPane(textArea); Scene scene = new Scene(root, 400, 400); primaryStage.setScene(scene); primaryStage.setTitle("Текстовый редактор"); primaryStage.show(); } public static void main(String[] args) { launch(args); } } - Входные данные: текст для ввода
- Решение:
Создание списка задач: Напишите приложение, которое позволяет пользователю добавлять и удалять задачи из списка.
- Решение:java
import javafx.application.Application; import javafx.scene.Scene; import javafx.scene.control.Button; import javafx.scene.control.ListView; import javafx.scene.control.TextField; import javafx.scene.layout.VBox; import javafx.stage.Stage; public class TodoListApp extends Application { @Override public void start(Stage primaryStage) { ListView<String> listView = new ListView<>(); TextField textField = new TextField(); Button addButton = new Button("Добавить"); Button removeButton = new Button("Удалить"); addButton.setOnAction(e -> { String task = textField.getText(); if (!task.isEmpty()) { listView.getItems().add(task); textField.clear(); } }); removeButton.setOnAction(e -> { String selectedTask = listView.getSelectionModel().getSelectedItem(); if (selectedTask != null) { listView.getItems().remove(selectedTask); } }); VBox vbox = new VBox(textField, addButton, removeButton, listView); Scene scene = new Scene(vbox, 300, 400); primaryStage.setScene(scene); primaryStage.show(); } public static void main(String[] args) { launch(args); } } - Входные данные: текст задачи для добавления
- Решение:
Создание приложения с настройками: Напишите приложение, которое позволяет пользователю изменять настройки (например, цвет фона).
- Решение:java
import javafx.application.Application; import javafx.scene.Scene; import javafx.scene.control.Button; import javafx.scene.layout.StackPane; import javafx.stage.Stage; public class SettingsApp extends Application { @Override public void start(Stage primaryStage) { StackPane root = new StackPane(); Scene scene = new Scene(root, 400, 400); primaryStage.setScene(scene); primaryStage.setTitle("Настройки"); Button button = new Button("Изменить цвет фона"); button.setOnAction(e -> root.setStyle("-fx-background-color: lightblue;")); root.getChildren().add(button); primaryStage.show(); } public static void main(String[] args) { launch(args); } } - Входные данные: изменение цвета фона
- Решение:
Создание приложения для отображения данных: Напишите приложение, которое отображает данные в таблице.
- Решение:java
import javafx.application.Application; import javafx.scene.Scene; import javafx.scene.control.TableColumn; import javafx.scene.control.TableView; import javafx.scene.control.cell.PropertyValueFactory; import javafx.scene.layout.StackPane; import javafx.stage.Stage; public class TableViewExample extends Application { public static class Person { private final String name; private final int age; public Person(String name, int age) { this.name = name; this.age = age; } public String getName() { return name; } public int getAge() { return age; } } @Override public void start(Stage primaryStage) { TableView<Person> table = new TableView<>(); TableColumn<Person, String> nameColumn = new TableColumn<>("Имя"); TableColumn<Person, Integer> ageColumn = new TableColumn<>("Возраст"); nameColumn.setCellValueFactory(new PropertyValueFactory<>("name")); ageColumn.setCellValueFactory(new PropertyValueFactory<>("age")); table.getColumns().add(nameColumn); table.getColumns().add(ageColumn); table.getItems().add(new Person("Алексей", 30)); table.getItems().add(new Person("Мария", 25)); StackPane root = new StackPane(table); Scene scene = new Scene(root, 300, 200); primaryStage.setScene(scene); primaryStage.show(); } public static void main(String[] args) { launch(args); } } - Входные данные: данные для отображения
- Решение:
Создание приложения с настройками цветовой схемы: Напишите приложение, которое позволяет пользователю выбирать цветовую схему для интерфейса.
- Решение:java
import javafx.application.Application; import javafx.scene.Scene; import javafx.scene.control.Button; import javafx.scene.layout.StackPane; import javafx.stage.Stage; public class ColorSchemeApp extends Application { @Override public void start(Stage primaryStage) { StackPane root = new StackPane(); Scene scene = new Scene(root, 400, 400); primaryStage.setScene(scene); primaryStage.setTitle("Выбор цветовой схемы"); Button button = new Button("Сменить цветовую схему"); button.setOnAction(e -> root.setStyle("-fx-background-color: #f0f0f0;")); root.getChildren().add(button); primaryStage.show(); } public static void main(String[] args) { launch(args); } } - Входные данные: выбор цветовой схемы
- Решение:
Создание игры с кнопками: Напишите простую игру, в которой пользователь нажимает кнопку, чтобы зарабатывать очки.
- Решение:java
import javafx.application.Application; import javafx.scene.Scene; import javafx.scene.control.Button; import javafx.scene.control.Label; import javafx.scene.layout.VBox; import javafx.stage.Stage; public class ClickGame extends Application { private int score = 0; @Override public void start(Stage primaryStage) { Label scoreLabel = new Label("Очки: " + score); Button button = new Button("Нажми меня!"); button.setOnAction(e -> { score++; scoreLabel.setText("Очки: " + score); }); VBox vbox = new VBox(scoreLabel, button); Scene scene = new Scene(vbox, 300, 200); primaryStage.setScene(scene); primaryStage.setTitle("Игра"); primaryStage.show(); } public static void main(String[] args) { launch(args); } } - Входные данные: нажатия на кнопку
- Решение:
Создание приложения для отслеживания времени: Напишите приложение, которое показывает текущее время и позволяет пользователю устанавливать таймер.
- Решение:java
import javafx.application.Application; import javafx.scene.Scene; import javafx.scene.control.Button; import javafx.scene.control.Label; import javafx.scene.control.TextField; import javafx.scene.layout.VBox; import javafx.stage.Stage; import java.util.Timer; import java.util.TimerTask; public class TimerApp extends Application { private Timer timer = new Timer(); @Override public void start(Stage primaryStage) { Label timeLabel = new Label("Текущее время: " + System.currentTimeMillis()); TextField textField = new TextField("Введите время в миллисекундах"); Button startButton = new Button("Запустить таймер"); startButton.setOnAction(e -> { long delay = Long.parseLong(textField.getText()); timer.schedule(new TimerTask() { @Override public void run() { System.out.println("Таймер сработал!"); } }, delay); }); VBox vbox = new VBox(timeLabel, textField, startButton); Scene scene = new Scene(vbox, 300, 200); primaryStage.setScene(scene); primaryStage.show(); } public static void main(String[] args) { launch(args); } } - Входные данные: время в миллисекундах для таймера
- Решение:
Создание приложения с графиками: Напишите приложение, которое отображает график данных.
- Решение:java
import javafx.application.Application; import javafx.scene.Scene; import javafx.scene.chart.LineChart; import javafx.scene.chart.NumberAxis; import javafx.scene.chart.XYChart; import javafx.stage.Stage; public class ChartExample extends Application { @Override public void start(Stage primaryStage) { NumberAxis xAxis = new NumberAxis(); NumberAxis yAxis = new NumberAxis(); LineChart<Number, Number> lineChart = new LineChart<>(xAxis, yAxis); XYChart.Series<Number, Number> series = new XYChart.Series<>(); series.setName("Данные"); series.getData().add(new XYChart.Data<>(1, 23)); series.getData().add(new XYChart.Data<>(2, 14)); series.getData().add(new XYChart.Data<>(3, 15)); lineChart.getData().add(series); Scene scene = new Scene(lineChart, 400, 300); primaryStage.setScene(scene); primaryStage.setTitle("График данных"); primaryStage.show(); } public static void main(String[] args) { launch(args); } } - Входные данные: данные для отображения на графике
- Решение:
ОПРЕДЕЛЕНИЕ ИНТЕРФЕЙСА В FXML
Базовые задачи
Создание простого интерфейса с кнопкой: Определите интерфейс с одной кнопкой, которая при нажатии выводит сообщение.
- Решение:xml
<!-- simple_interface.fxml --> <VBox xmlns:fx="http://javafx.com/fxml" fx:controller="controller.SimpleController"> <Button text="Нажми меня" onAction="#handleButtonClick"/> </VBox>java// SimpleController.java package controller; import javafx.fxml.FXML; import javafx.scene.control.Button; public class SimpleController { @FXML private Button button; @FXML public void handleButtonClick() { System.out.println("Кнопка нажата!"); } } - Входные данные: нет
- Решение:
Создание текстового поля и кнопки: Создайте интерфейс с текстовым полем и кнопкой. При нажатии на кнопку текст из текстового поля выводится в консоль.
- Решение:xml
<VBox xmlns:fx="http://javafx.com/fxml" fx:controller="controller.TextFieldController"> <TextField fx:id="textField" /> <Button text="Показать текст" onAction="#showText" /> </VBox>java// TextFieldController.java package controller; import javafx.fxml.FXML; import javafx.scene.control.TextField; public class TextFieldController { @FXML private TextField textField; @FXML public void showText() { System.out.println(textField.getText()); } } - Входные данные: текст для отображения
- Решение:
Создание интерфейса с меткой и текстовым полем: Создайте интерфейс с меткой и текстовым полем. При вводе текста в текстовое поле он отображается в метке.
- Решение:xml
<VBox xmlns:fx="http://javafx.com/fxml" fx:controller="controller.LabelController"> <Label fx:id="label" text="Введите текст" /> <TextField fx:id="textField" onKeyReleased="#updateLabel" /> </VBox>java// LabelController.java package controller; import javafx.fxml.FXML; import javafx.scene.control.Label; import javafx.scene.control.TextField; public class LabelController { @FXML private Label label; @FXML private TextField textField; @FXML public void updateLabel() { label.setText(textField.getText()); } } - Входные данные: текст для обновления метки
- Решение:
Создание интерфейса с комбобоксом: Создайте интерфейс с комбобоксом. При выборе элемента из комбобокса он отображается в метке.
- Решение:xml
<VBox xmlns:fx="http://javafx.com/fxml" fx:controller="controller.ComboBoxController"> <ComboBox fx:id="comboBox" onAction="#updateLabel"> <items> <String fx:value="Элемент 1" /> <String fx:value="Элемент 2" /> <String fx:value="Элемент 3" /> </items> </ComboBox> <Label fx:id="label" /> </VBox>java// ComboBoxController.java package controller; import javafx.fxml.FXML; import javafx.scene.control.ComboBox; import javafx.scene.control.Label; public class ComboBoxController { @FXML private ComboBox<String> comboBox; @FXML private Label label; @FXML public void updateLabel() { label.setText(comboBox.getValue()); } } - Входные данные: выбор элемента из комбобокса
- Решение:
Создание интерфейса с радиокнопками: Создайте интерфейс с радиокнопками. При выборе радиокнопки в метке отображается соответствующий текст.
- Решение:xml
<VBox xmlns:fx="http://javafx.com/fxml" fx:controller="controller.RadioButtonController"> <ToggleGroup fx:id="toggleGroup"> <RadioButton fx:id="radio1" text="Выбор 1" onAction="#updateLabel" /> <RadioButton fx:id="radio2" text="Выбор 2" onAction="#updateLabel" /> </ToggleGroup> <Label fx:id="label" /> </VBox>java// RadioButtonController.java package controller; import javafx.fxml.FXML; import javafx.scene.control.Label; import javafx.scene.control.RadioButton; import javafx.scene.control.ToggleGroup; public class RadioButtonController { @FXML private Label label; @FXML private ToggleGroup toggleGroup; @FXML public void updateLabel() { RadioButton selected = (RadioButton) toggleGroup.getSelectedToggle(); label.setText(selected.getText()); } } - Входные данные: выбор радиокнопки
- Решение:
Создание интерфейса с чекбоксом: Создайте интерфейс с чекбоксом. При изменении состояния чекбокса метка обновляется.
- Решение:xml
<VBox xmlns:fx="http://javafx.com/fxml" fx:controller="controller.CheckBoxController"> <CheckBox fx:id="checkBox" text="Выберите меня" onAction="#updateLabel" /> <Label fx:id="label" /> </VBox>java// CheckBoxController.java package controller; import javafx.fxml.FXML; import javafx.scene.control.CheckBox; import javafx.scene.control.Label; public class CheckBoxController { @FXML private CheckBox checkBox; @FXML private Label label; @FXML public void updateLabel() { label.setText(checkBox.isSelected() ? "Чекбокс выбран" : "Чекбокс не выбран"); } } - Входные данные: изменение состояния чекбокса
- Решение:
Создание интерфейса с ProgressBar: Создайте интерфейс с ProgressBar. При нажатии на кнопку прогресс увеличивается.
- Решение:xml
<VBox xmlns:fx="http://javafx.com/fxml" fx:controller="controller.ProgressBarController"> <ProgressBar fx:id="progressBar" /> <Button text="Увеличить прогресс" onAction="#increaseProgress" /> </VBox>java// ProgressBarController.java package controller; import javafx.fxml.FXML; import javafx.scene.control.Button; import javafx.scene.control.ProgressBar; public class ProgressBarController { @FXML private ProgressBar progressBar; private double progress = 0; @FXML public void increaseProgress() { progress += 0.1; progressBar.setProgress(progress); } } - Входные данные: нажатие на кнопку
- Решение:
Создание интерфейса с TabPane: Создайте интерфейс с TabPane, в котором будет несколько вкладок.
- Решение:xml
<TabPane xmlns:fx="http://javafx.com/fxml"> <tabs> <Tab text="Вкладка 1"> <Label text="Содержимое вкладки 1" /> </Tab> <Tab text="Вкладка 2"> <Label text="Содержимое вкладки 2" /> </Tab> </tabs> </TabPane> - Входные данные: нет
- Решение:
Создание интерфейса с GridPane: Создайте интерфейс с GridPane, где будет расположено несколько кнопок.
- Решение:xml
<GridPane xmlns:fx="http://javafx.com/fxml"> <Button text="Кнопка 1" gridx="0" gridy="0" /> <Button text="Кнопка 2" gridx="1" gridy="0" /> <Button text="Кнопка 3" gridx="0" gridy="1" /> <Button text="Кнопка 4" gridx="1" gridy="1" /> </GridPane> - Входные данные: нет
- Решение:
Создание интерфейса с AnchorPane: Создайте интерфейс с AnchorPane и разместите элементы управления.
- Решение:xml
<AnchorPane xmlns:fx="http://javafx.com/fxml"> <Button text="Кнопка 1" anchorPane.leftAnchor="10" anchorPane.topAnchor="10" /> <Label text="Метка" anchorPane.leftAnchor="10" anchorPane.topAnchor="50" /> </AnchorPane> - Входные данные: нет
- Решение:
Сложные задачи
Создание интерфейса с несколькими элементами управления: Создайте интерфейс, который включает текстовое поле, комбобокс, чекбокс и кнопку. При нажатии кнопки выводится текст из текстового поля и выбранный элемент из комбобокса.
- Решение:xml
<VBox xmlns:fx="http://javafx.com/fxml" fx:controller="controller.ComplexController"> <TextField fx:id="textField" /> <ComboBox fx:id="comboBox"> <items> <String fx:value="Элемент 1" /> <String fx:value="Элемент 2" /> </items> </ComboBox> <CheckBox fx:id="checkBox" text="Выберите меня" /> <Button text="Отправить" onAction="#handleSubmit" /> </VBox>java// ComplexController.java package controller; import javafx.fxml.FXML; import javafx.scene.control.CheckBox; import javafx.scene.control.ComboBox; import javafx.scene.control.TextField; public class ComplexController { @FXML private TextField textField; @FXML private ComboBox<String> comboBox; @FXML private CheckBox checkBox; @FXML public void handleSubmit() { System.out.println("Текст: " + textField.getText()); System.out.println("Выбор: " + comboBox.getValue()); System.out.println("Чекбокс: " + (checkBox.isSelected() ? "выбран" : "не выбран")); } } - Входные данные: текст, выбор из комбобокса, состояние чекбокса
- Решение:
Создание интерфейса с динамическим добавлением элементов: Создайте интерфейс, где можно динамически добавлять текстовые поля по нажатию кнопки.
- Решение:xml
<VBox xmlns:fx="http://javafx.com/fxml" fx:controller="controller.DynamicController"> <Button text="Добавить текстовое поле" onAction="#addTextField" /> <VBox fx:id="dynamicContainer" /> </VBox>java// DynamicController.java package controller; import javafx.fxml.FXML; import javafx.scene.control.TextField; import javafx.scene.layout.VBox; public class DynamicController { @FXML private VBox dynamicContainer; @FXML public void addTextField() { TextField newField = new TextField("Новое текстовое поле"); dynamicContainer.getChildren().add(newField); } } - Входные данные: нажатие кнопки
- Решение:
Создание интерфейса с таблицей и кнопкой добавления: Создайте интерфейс с таблицей, в которой можно добавлять строки по нажатию кнопки.
- Решение:xml
<VBox xmlns:fx="http://javafx.com/fxml" fx:controller="controller.TableController"> <TableView fx:id="tableView"> <columns> <TableColumn text="Имя" /> <TableColumn text="Возраст" /> </columns> </TableView> <Button text="Добавить строку" onAction="#addRow" /> </VBox>java// TableController.java package controller; import javafx.collections.FXCollections; import javafx.collections.ObservableList; import javafx.fxml.FXML; import javafx.scene.control.TableColumn; import javafx.scene.control.TableView; public class TableController { @FXML private TableView<Person> tableView; private ObservableList<Person> data = FXCollections.observableArrayList(); @FXML public void addRow() { data.add(new Person("Новое имя", 20)); tableView.setItems(data); } public static class Person { private final String name; private final int age; public Person(String name, int age) { this.name = name; this.age = age; } public String getName() { return name; } public int getAge() { return age; } } } - Входные данные: нажатие кнопки
- Решение:
Создание интерфейса с формой ввода и валидацией: Создайте интерфейс с формой для ввода данных. При нажатии на кнопку данные валидируются, и выводится сообщение об успехе или ошибке.
- Решение:xml
<VBox xmlns:fx="http://javafx.com/fxml" fx:controller="controller.ValidationController"> <TextField fx:id="nameField" promptText="Имя" /> <TextField fx:id="ageField" promptText="Возраст" /> <Button text="Отправить" onAction="#handleSubmit" /> <Label fx:id="messageLabel" /> </VBox>java// ValidationController.java package controller; import javafx.fxml.FXML; import javafx.scene.control.Label; import javafx.scene.control.TextField; public class ValidationController { @FXML private TextField nameField; @FXML private TextField ageField; @FXML private Label messageLabel; @FXML public void handleSubmit() { String name = nameField.getText(); String ageText = ageField.getText(); if (name.isEmpty() || ageText.isEmpty()) { messageLabel.setText("Пожалуйста, заполните все поля."); return; } try { int age = Integer.parseInt(ageText); messageLabel.setText("Данные отправлены: " + name + ", " + age); } catch (NumberFormatException e) { messageLabel.setText("Возраст должен быть числом."); } } } - Входные данные: имя и возраст
- Решение:
Создание интерфейса с графическим представлением: Создайте интерфейс с графическим представлением данных, используя Chart.
- Решение:xml
<VBox xmlns:fx="http://javafx.com/fxml" fx:controller="controller.ChartController"> <LineChart fx:id="lineChart"> <xAxis> <NumberAxis /> </xAxis> <yAxis> <NumberAxis /> </yAxis> </LineChart> <Button text="Добавить данные" onAction="#addData" /> </VBox>java// ChartController.java package controller; import javafx.fxml.FXML; import javafx.scene.chart.LineChart; import javafx.scene.chart.NumberAxis; import javafx.scene.chart.XYChart; public class ChartController { @FXML private LineChart<Number, Number> lineChart; private int dataCount = 0; @FXML public void addData() { dataCount++; XYChart.Series<Number, Number> series = new XYChart.Series<>(); series.getData().add(new XYChart.Data<>(dataCount, Math.random() * 100)); lineChart.getData().add(series); } } - Входные данные: нажатие кнопки
- Решение:
Создание интерфейса с анимацией: Создайте интерфейс с элементами, которые анимируются при нажатии на кнопку.
- Решение:xml
<VBox xmlns:fx="http://javafx.com/fxml" fx:controller="controller.AnimationController"> <Rectangle fx:id="rectangle" width="100" height="100" fill="blue" /> <Button text="Анимировать" onAction="#animate" /> </VBox>java// AnimationController.java package controller; import javafx.animation.TranslateTransition; import javafx.fxml.FXML; import javafx.scene.shape.Rectangle; import javafx.util.Duration; public class AnimationController { @FXML private Rectangle rectangle; @FXML public void animate() { TranslateTransition transition = new TranslateTransition(Duration.seconds(2), rectangle); transition.setByX(200); transition.play(); } } - Входные данные: нажатие кнопки
- Решение:
Создание интерфейса с панелью инструментов: Создайте интерфейс с панелью инструментов, включающей несколько кнопок для выполнения различных действий.
- Решение:xml
<ToolBar xmlns:fx="http://javafx.com/fxml"> <Button text="Действие 1" onAction="#handleAction1" /> <Button text="Действие 2" onAction="#handleAction2" /> </ToolBar>java// ToolBarController.java package controller; import javafx.fxml.FXML; public class ToolBarController { @FXML public void handleAction1() { System.out.println("Действие 1 выполнено"); } @FXML public void handleAction2() { System.out.println("Действие 2 выполнено"); } } - Входные данные: нажатие кнопок
- Решение:
Создание интерфейса с календарем: Создайте интерфейс с элементом календаря. При выборе даты выводится сообщение.
- Решение:xml
<VBox xmlns:fx="http://javafx.com/fxml" fx:controller="controller.CalendarController"> <DatePicker fx:id="datePicker" onAction="#showSelectedDate" /> <Label fx:id="label" /> </VBox>java// CalendarController.java package controller; import javafx.fxml.FXML; import javafx.scene.control.DatePicker; import javafx.scene.control.Label; public class CalendarController { @FXML private DatePicker datePicker; @FXML private Label label; @FXML public void showSelectedDate() { label.setText("Выбрана дата: " + datePicker.getValue()); } } - Входные данные: выбор даты
- Решение:
Создание интерфейса с локализацией: Создайте интерфейс, который поддерживает несколько языков, и изменяйте текст на выбранном языке.
- Решение:xml
<VBox xmlns:fx="http://javafx.com/fxml" fx:controller="controller.LocalizationController"> <ComboBox fx:id="languageComboBox" onAction="#changeLanguage"> <items> <String fx:value="Русский" /> <String fx:value="English" /> </items> </ComboBox> <Label fx:id="label" /> </VBox>java// LocalizationController.java package controller; import javafx.fxml.FXML; import javafx.scene.control.ComboBox; import javafx.scene.control.Label; public class LocalizationController { @FXML private Label label; @FXML private ComboBox<String> languageComboBox; @FXML public void changeLanguage() { String selectedLanguage = languageComboBox.getValue(); if ("Русский".equals(selectedLanguage)) { label.setText("Привет, мир!"); } else { label.setText("Hello, World!"); } } } - Входные данные: выбор языка
- Решение:
Создание интерфейса с поддержкой тем: Создайте интерфейс с возможностью переключения тем.
- Решение:xml
<VBox xmlns:fx="http://javafx.com/fxml" fx:controller="controller.ThemeController"> <Button text="Темная тема" onAction="#setDarkTheme" /> <Button text="Светлая тема" onAction="#setLightTheme" /> </VBox>java// ThemeController.java package controller; import javafx.fxml.FXML; import javafx.scene.Scene; import javafx.scene.control.Button; import javafx.scene.layout.VBox; public class ThemeController { @FXML private VBox vBox; @FXML public void setDarkTheme() { vBox.setStyle("-fx-background-color: black; -fx-text-fill: white;"); } @FXML public void setLightTheme() { vBox.setStyle("-fx-background-color: white; -fx-text-fill: black;"); } } - Входные данные: нажатие кнопок
- Решение:
КОНТРОЛЛЕРЫ И ВЗАИМОДЕЙСТВИЕ С ПОЛЬЗОВАТЕЛЕМ
Базовые задачи
Создание контроллера для простого интерфейса: Создайте контроллер для интерфейса с одной кнопкой. При нажатии на кнопку выводится сообщение.
- Решение:xml
<VBox xmlns:fx="http://javafx.com/fxml" fx:controller="controller.SimpleController"> <Button text="Нажми меня" onAction="#handleButtonClick"/> </VBox>java// SimpleController.java package controller; import javafx.fxml.FXML; import javafx.scene.control.Button; public class SimpleController { @FXML private Button button; @FXML public void handleButtonClick() { System.out.println("Кнопка нажата!"); } } - Входные данные: нет
- Решение:
Создание контроллера с текстовым полем: Создайте контроллер, который получает текст из текстового поля при нажатии кнопки и выводит его в консоль.
- Решение:xml
<VBox xmlns:fx="http://javafx.com/fxml" fx:controller="controller.TextFieldController"> <TextField fx:id="textField" /> <Button text="Показать текст" onAction="#showText" /> </VBox>java// TextFieldController.java package controller; import javafx.fxml.FXML; import javafx.scene.control.TextField; public class TextFieldController { @FXML private TextField textField; @FXML public void showText() { System.out.println(textField.getText()); } } - Входные данные: текст для отображения
- Решение:
Создание контроллера для выбора элемента из ComboBox: Создайте контроллер, который выводит выбранный элемент из ComboBox в метку.
- Решение:xml
<VBox xmlns:fx="http://javafx.com/fxml" fx:controller="controller.ComboBoxController"> <ComboBox fx:id="comboBox" onAction="#updateLabel"> <items> <String fx:value="Элемент 1" /> <String fx:value="Элемент 2" /> </items> </ComboBox> <Label fx:id="label" /> </VBox>java// ComboBoxController.java package controller; import javafx.fxml.FXML; import javafx.scene.control.ComboBox; import javafx.scene.control.Label; public class ComboBoxController { @FXML private ComboBox<String> comboBox; @FXML private Label label; @FXML public void updateLabel() { label.setText(comboBox.getValue()); } } - Входные данные: выбор элемента из комбобокса
- Решение:
Создание контроллера для радиокнопок: Создайте контроллер, который выводит текст выбранной радиокнопки в метку.
- Решение:xml
<VBox xmlns:fx="http://javafx.com/fxml" fx:controller="controller.RadioButtonController"> <ToggleGroup fx:id="toggleGroup"> <RadioButton fx:id="radio1" text="Выбор 1" onAction="#updateLabel" /> <RadioButton fx:id="radio2" text="Выбор 2" onAction="#updateLabel" /> </ToggleGroup> <Label fx:id="label" /> </VBox>java// RadioButtonController.java package controller; import javafx.fxml.FXML; import javafx.scene.control.Label; import javafx.scene.control.RadioButton; import javafx.scene.control.ToggleGroup; public class RadioButtonController { @FXML private Label label; @FXML private ToggleGroup toggleGroup; @FXML public void updateLabel() { RadioButton selected = (RadioButton) toggleGroup.getSelectedToggle(); label.setText(selected.getText()); } } - Входные данные: выбор радиокнопки
- Решение:
Создание контроллера для чекбокса: Создайте контроллер, который обновляет метку в зависимости от состояния чекбокса.
- Решение:xml
<VBox xmlns:fx="http://javafx.com/fxml" fx:controller="controller.CheckBoxController"> <CheckBox fx:id="checkBox" text="Выберите меня" onAction="#updateLabel" /> <Label fx:id="label" /> </VBox>java// CheckBoxController.java package controller; import javafx.fxml.FXML; import javafx.scene.control.CheckBox; import javafx.scene.control.Label; public class CheckBoxController { @FXML private CheckBox checkBox; @FXML private Label label; @FXML public void updateLabel() { label.setText(checkBox.isSelected() ? "Чекбокс выбран" : "Чекбокс не выбран"); } } - Входные данные: изменение состояния чекбокса
- Решение:
Создание контроллера с ProgressBar: Создайте контроллер для увеличения значения ProgressBar при нажатии на кнопку.
- Решение:xml
<VBox xmlns:fx="http://javafx.com/fxml" fx:controller="controller.ProgressBarController"> <ProgressBar fx:id="progressBar" /> <Button text="Увеличить прогресс" onAction="#increaseProgress" /> </VBox>java// ProgressBarController.java package controller; import javafx.fxml.FXML; import javafx.scene.control.Button; import javafx.scene.control.ProgressBar; public class ProgressBarController { @FXML private ProgressBar progressBar; private double progress = 0; @FXML public void increaseProgress() { progress += 0.1; if (progress > 1) { progress = 1; } progressBar.setProgress(progress); } } - Входные данные: нажатие кнопки
- Решение:
Создание контроллера с таблицей: Создайте контроллер для отображения данных в таблице и добавления новых строк.
- Решение:xml
<VBox xmlns:fx="http://javafx.com/fxml" fx:controller="controller.TableViewController"> <TableView fx:id="tableView"> <columns> <TableColumn text="Имя" /> <TableColumn text="Возраст" /> </columns> </TableView> <Button text="Добавить" onAction="#addRow" /> </VBox>java// TableViewController.java package controller; import javafx.collections.FXCollections; import javafx.collections.ObservableList; import javafx.fxml.FXML; import javafx.scene.control.TableColumn; import javafx.scene.control.TableView; public class TableViewController { @FXML private TableView<Person> tableView; private ObservableList<Person> data = FXCollections.observableArrayList(); @FXML public void addRow() { data.add(new Person("Имя", 20)); tableView.setItems(data); } public static class Person { private String name; private int age; public Person(String name, int age) { this.name = name; this.age = age; } public String getName() { return name; } public int getAge() { return age; } } } - Входные данные: нажатие кнопки
- Решение:
Создание контроллера для загрузки файла: Создайте контроллер, который открывает диалог для выбора файла и выводит путь к файлу в метке.
- Решение:xml
<VBox xmlns:fx="http://javafx.com/fxml" fx:controller="controller.FileChooserController"> <Button text="Выбрать файл" onAction="#chooseFile" /> <Label fx:id="filePathLabel" /> </VBox>java// FileChooserController.java package controller; import javafx.fxml.FXML; import javafx.scene.control.Label; import javafx.stage.FileChooser; import java.io.File; public class FileChooserController { @FXML private Label filePathLabel; @FXML public void chooseFile() { FileChooser fileChooser = new FileChooser(); File file = fileChooser.showOpenDialog(null); if (file != null) { filePathLabel.setText(file.getAbsolutePath()); } } } - Входные данные: выбор файла
- Решение:
Создание контроллера для загрузки изображений: Создайте контроллер, который позволяет загружать изображения и отображать их в ImageView.
- Решение:xml
<VBox xmlns:fx="http://javafx.com/fxml" fx:controller="controller.ImageLoaderController"> <Button text="Загрузить изображение" onAction="#loadImage" /> <ImageView fx:id="imageView" /> </VBox>java// ImageLoaderController.java package controller; import javafx.fxml.FXML; import javafx.scene.image.Image; import javafx.scene.image.ImageView; import javafx.stage.FileChooser; import java.io.File; public class ImageLoaderController { @FXML private ImageView imageView; @FXML public void loadImage() { FileChooser fileChooser = new FileChooser(); fileChooser.getExtensionFilters().add(new FileChooser.ExtensionFilter("Image Files", "*.png", "*.jpg", "*.gif")); File file = fileChooser.showOpenDialog(null); if (file != null) { imageView.setImage(new Image(file.toURI().toString())); } } } - Входные данные: выбор изображения
- Решение:
Создание контроллера для изменения стиля: Создайте контроллер, который изменяет стиль кнопки по нажатию.
- Решение:xml
<VBox xmlns:fx="http://javafx.com/fxml" fx:controller="controller.StyleController"> <Button fx:id="button" text="Нажми меня" onAction="#changeStyle" /> </VBox>java// StyleController.java package controller; import javafx.fxml.FXML; import javafx.scene.control.Button; public class StyleController { @FXML private Button button; @FXML public void changeStyle() { button.setStyle("-fx-background-color: red; -fx-text-fill: white;"); } } - Входные данные: нажатие кнопки
- Решение:
ВИЗУАЛЬНЫЕ КОМПОНЕНТЫ И МАКЕТЫ
Базовые задачи
Создание интерфейса с использованием GridPane: Создайте интерфейс с GridPane, в котором размещены метки и текстовые поля.
- Решение:xml
<GridPane xmlns:fx="http://javafx.com/fxml"> <Label text="Имя:" gridX="0" gridY="0"/> <TextField fx:id="nameField" gridX="1" gridY="0"/> <Label text="Возраст:" gridX="0" gridY="1"/> <TextField fx:id="ageField" gridX="1" gridY="1"/> </GridPane> - Входные данные: нет
- Решение:
Создание интерфейса с использованием HBox и VBox: Создайте интерфейс, использующий HBox для размещения кнопок и VBox для размещения текстовых полей.
- Решение:xml
<VBox xmlns:fx="http://javafx.com/fxml"> <HBox> <Button text="Кнопка 1" /> <Button text="Кнопка 2" /> </HBox> <TextField promptText="Введите текст" /> </VBox> - Входные данные: нет
- Решение:
Создание интерфейса с использованием StackPane: Создайте интерфейс с StackPane, в котором размещены несколько элементов, накладывающихся друг на друга.
- Решение:xml
<StackPane xmlns:fx="http://javafx.com/fxml"> <Label text="На заднем плане" style="-fx-background-color: lightblue;" /> <Label text="На переднем плане" style="-fx-background-color: lightgreen;" /> </StackPane> - Входные данные: нет
- Решение:
Создание интерфейса с использованием AnchorPane: Создайте интерфейс с AnchorPane, позволяющим свободно размещать элементы.
- Решение:xml
<AnchorPane xmlns:fx="http://javafx.com/fxml"> <Label text="Я слева" layoutX="10" layoutY="10" /> <Label text="Я справа" layoutX="300" layoutY="10" /> </AnchorPane> - Входные данные: нет
- Решение:
Создание интерфейса с использованием TitledPane: Создайте интерфейс с TitledPane, содержащим различные элементы управления.
- Решение:xml
<TitledPane xmlns:fx="http://javafx.com/fxml" text="Заголовок"> <VBox> <Label text="Элемент 1" /> <Label text="Элемент 2" /> </VBox> </TitledPane> - Входные данные: нет
- Решение:
Создание интерфейса с TabPane: Создайте интерфейс с TabPane, содержащим несколько вкладок.
- Решение:xml
<TabPane xmlns:fx="http://javafx.com/fxml"> <Tab text="Вкладка 1"> <Label text="Содержимое вкладки 1" /> </Tab> <Tab text="Вкладка 2"> <Label text="Содержимое вкладки 2" /> </Tab> </TabPane> - Входные данные: нет
- Решение:
Создание интерфейса с использованием ListView: Создайте интерфейс с ListView для отображения списка элементов.
- Решение:xml
<VBox xmlns:fx="http://javafx.com/fxml"> <ListView fx:id="listView"> <items> <String fx:value="Элемент 1" /> <String fx:value="Элемент 2" /> </items> </ListView> </VBox> - Входные данные: нет
- Решение:
Создание интерфейса с использованием ProgressIndicator: Создайте интерфейс с ProgressIndicator для отображения прогресса выполнения задачи.
- Решение:xml
<VBox xmlns:fx="http://javafx.com/fxml"> <ProgressIndicator fx:id="progressIndicator" /> </VBox> - Входные данные: нет
- Решение:
Создание интерфейса с использованием Slider: Создайте интерфейс с Slider для выбора значения.
- Решение:xml
<VBox xmlns:fx="http://javafx.com/fxml"> <Slider fx:id="slider" min="0" max="100" /> </VBox> - Входные данные: изменение значения слайдера
- Решение:
Создание интерфейса с использованием SplitPane: Создайте интерфейс с SplitPane для разделения области отображения.
- Решение:xml
<SplitPane xmlns:fx="http://javafx.com/fxml"> <items> <VBox> <Label text="Левый панель" /> </VBox> <VBox> <Label text="Правый панель" /> </VBox> </items> </SplitPane> - Входные данные: нет
- Решение:
Дополнительные задачи
Создание интерфейса с использованием CSS: Создайте интерфейс и примените к нему стили CSS.
- Решение:xml
<VBox xmlns:fx="http://javafx.com/fxml" styleClass="my-style"> <Button text="Кнопка" /> </VBox>css.my-style { -fx-background-color: lightgray; } - Входные данные: нет
- Решение:
Создание интерфейса с использованием анимации: Создайте интерфейс с анимацией для кнопки.
- Решение:xml
<VBox xmlns:fx="http://javafx.com/fxml"> <Button fx:id="button" text="Анимированная кнопка" onMouseEntered="#animateButton"/> </VBox>java// AnimationController.java package controller; import javafx.animation.ScaleTransition; import javafx.fxml.FXML; import javafx.scene.control.Button; import javafx.util.Duration; public class AnimationController { @FXML private Button button; @FXML public void animateButton() { ScaleTransition st = new ScaleTransition(Duration.millis(500), button); st.setFromX(1); st.setFromY(1); st.setToX(1.2); st.setToY(1.2); st.setCycleCount(2); st.setAutoReverse(true); st.play(); } } - Входные данные: наведение курсора на кнопку
- Решение:
Создание интерфейса с помощью Canvas: Создайте интерфейс, использующий Canvas для рисования.
- Решение:xml
<Canvas xmlns:fx="http://javafx.com/fxml" fx:id="canvas" width="400" height="400" />java// CanvasController.java package controller; import javafx.fxml.FXML; import javafx.scene.canvas.Canvas; import javafx.scene.canvas.GraphicsContext; import javafx.scene.paint.Color; public class CanvasController { @FXML private Canvas canvas; @FXML public void initialize() { GraphicsContext gc = canvas.getGraphicsContext2D(); gc.setFill(Color.BLUE); gc.fillRect(50, 50, 300, 300); } } - Входные данные: нет
- Решение:
Создание интерфейса для работы с веб-сервисами: Создайте интерфейс для получения данных из веб-сервиса и отображения их в таблице.
- Решение:xml
<VBox xmlns:fx="http://javafx.com/fxml" fx:controller="controller.WebServiceController"> <Button text="Получить данные" onAction="#fetchData" /> <TableView fx:id="tableView" /> </VBox>java// WebServiceController.java package controller; import javafx.fxml.FXML; import javafx.scene.control.TableView; public class WebServiceController { @FXML private TableView<Data> tableView; @FXML public void fetchData() { // Логика для получения данных из веб-сервиса } public static class Data { private String field1; private String field2; public Data(String field1, String field2) { this.field1 = field1; this.field2 = field2; } public String getField1() { return field1; } public String getField2() { return field2; } } } - Входные данные: нажатие кнопки
- Решение:
Создание интерфейса для работы с базой данных: Создайте интерфейс для отображения данных из базы данных.
- Решение:xml
<VBox xmlns:fx="http://javafx.com/fxml" fx:controller="controller.DatabaseController"> <Button text="Загрузить данные" onAction="#loadData" /> <TableView fx:id="tableView" /> </VBox>java// DatabaseController.java package controller; import javafx.fxml.FXML; import javafx.scene.control.TableView; public class DatabaseController { @FXML private TableView<Data> tableView; @FXML public void loadData() { // Логика для загрузки данных из базы данных } public static class Data { private String field1; private String field2; public Data(String field1, String field2) { this.field1 = field1; this.field2 = field2; } public String getField1() { return field1; } public String getField2() { return field2; } } } - Входные данные: нажатие кнопки
- Решение:
Создание интерфейса для работы с графиками: Создайте интерфейс для отображения графиков с использованием сторонних библиотек.
- Решение:xml
<VBox xmlns:fx="http://javafx.com/fxml" fx:controller="controller.ChartController"> <Button text="Построить график" onAction="#drawChart" /> <VBox fx:id="chartContainer" /> </VBox>java// ChartController.java package controller; import javafx.fxml.FXML; import javafx.scene.layout.VBox; public class ChartController { @FXML private VBox chartContainer; @FXML public void drawChart() { // Логика для построения графика } } - Входные данные: нажатие кнопки
- Решение:
Создание интерфейса для настройки приложения: Создайте интерфейс с настройками приложения, позволяющий пользователю изменять параметры.
- Решение:xml
<VBox xmlns:fx="http://javafx.com/fxml" fx:controller="controller.SettingsController"> <Label text="Настройки приложения" /> <CheckBox fx:id="checkbox1" text="Опция 1" /> <CheckBox fx:id="checkbox2" text="Опция 2" /> <Button text="Сохранить настройки" onAction="#saveSettings" /> </VBox>java// SettingsController.java package controller; import javafx.fxml.FXML; import javafx.scene.control.CheckBox; public class SettingsController { @FXML private CheckBox checkbox1; @FXML private CheckBox checkbox2; @FXML public void saveSettings() { // Логика для сохранения настроек } } - Входные данные: нажатие кнопки
- Решение:
Создание интерфейса для ведения заметок: Создайте интерфейс для создания и отображения заметок.
- Решение:xml
<VBox xmlns:fx="http://javafx.com/fxml" fx:controller="controller.NoteController"> <TextArea fx:id="textArea" /> <Button text="Сохранить заметку" onAction="#saveNote" /> </VBox>java// NoteController.java package controller; import javafx.fxml.FXML; import javafx.scene.control.TextArea; public class NoteController { @FXML private TextArea textArea; @FXML public void saveNote() { String note = textArea.getText(); // Логика для сохранения заметки } } - Входные данные: нажатие кнопки
- Решение:
Создание интерфейса для работы с таймерами: Создайте интерфейс для настройки таймера.
- Решение:xml
<VBox xmlns:fx="http://javafx.com/fxml" fx:controller="controller.TimerController"> <Label text="Установить таймер (в секундах):" /> <TextField fx:id="timeField" /> <Button text="Запустить таймер" onAction="#startTimer" /> </VBox>java// TimerController.java package controller; import javafx.fxml.FXML; import javafx.scene.control.TextField; public class TimerController { @FXML private TextField timeField; @FXML public void startTimer() { int seconds = Integer.parseInt(timeField.getText()); // Логика для запуска таймера } } - Входные данные: нажатие кнопки
- Решение:
Создание интерфейса для отображения погоды: Создайте интерфейс для отображения текущей погоды.
- Решение:xml
<VBox xmlns:fx="http://javafx.com/fxml" fx:controller="controller.WeatherController"> <Button text="Получить погоду" onAction="#fetchWeather" /> <Label fx:id="weatherLabel" /> </VBox>java// WeatherController.java package controller; import javafx.fxml.FXML; import javafx.scene.control.Label; public class WeatherController { @FXML private Label weatherLabel; @FXML public void fetchWeather() { // Логика для получения погоды } } - Входные данные: нажатие кнопки
- Решение:
КНОПКИ И МЕТКИ
Базовые задачи (20)
Создать кнопку и метку: Создайте кнопку, которая при нажатии изменяет текст метки на "Кнопка нажата".
- Решение:java
@FXML private Button button; @FXML private Label label; @FXML public void handleButtonClick() { label.setText("Кнопка нажата"); } - Входные данные: нажатие кнопки
- Решение:
Кнопка с счетчиком: Создайте кнопку, которая при каждом нажатии увеличивает счетчик и отображает его на метке.
- Решение:java
private int count = 0; @FXML public void handleButtonClick() { count++; label.setText("Счетчик: " + count); } - Входные данные: нажатие кнопки
- Решение:
Кнопка для очистки метки: Создайте кнопку, которая очищает текст метки.
- Решение:java
@FXML public void handleClearButtonClick() { label.setText(""); } - Входные данные: нажатие кнопки
- Решение:
Кнопка с эффектом: Создайте кнопку, которая меняет цвет при наведении курсора.
- Решение:java
button.setOnMouseEntered(e -> button.setStyle("-fx-background-color: lightblue;")); button.setOnMouseExited(e -> button.setStyle("")); - Входные данные: наведение курсора на кнопку
- Решение:
Кнопка для выхода: Создайте кнопку, которая закрывает приложение при нажатии.
- Решение:java
@FXML public void handleExitButtonClick() { System.exit(0); } - Входные данные: нажатие кнопки
- Решение:
Кнопка для смены текста: Создайте кнопку, которая меняет текст метки на случайный.
- Решение:java
private String[] texts = {"Текст 1", "Текст 2", "Текст 3"}; @FXML public void handleChangeTextButtonClick() { int index = (int) (Math.random() * texts.length); label.setText(texts[index]); } - Входные данные: нажатие кнопки
- Решение:
Кнопка для отображения диалогового окна: Создайте кнопку, которая при нажатии отображает диалоговое окно с сообщением.
- Решение:java
@FXML public void handleShowDialogButtonClick() { Alert alert = new Alert(Alert.AlertType.INFORMATION); alert.setTitle("Информация"); alert.setHeaderText(null); alert.setContentText("Это диалоговое окно."); alert.showAndWait(); } - Входные данные: нажатие кнопки
- Решение:
Кнопка для отображения времени: Создайте кнопку, которая при нажатии отображает текущее время в метке.
- Решение:java
@FXML public void handleShowTimeButtonClick() { String currentTime = LocalTime.now().format(DateTimeFormatter.ofPattern("HH:mm:ss")); label.setText("Текущее время: " + currentTime); } - Входные данные: нажатие кнопки
- Решение:
Кнопка с изображением: Создайте кнопку, которая отображает изображение.
- Решение:java
Image img = new Image("file:path/to/image.png"); button.setGraphic(new ImageView(img)); - Входные данные: нет
- Решение:
Кнопка для изменения фона: Создайте кнопку, которая меняет фон приложения на случайный цвет.
- Решение:java
@FXML public void handleChangeBackgroundColorButtonClick() { String color = String.format("#%06X", (int)(Math.random() * 0xFFFFFF)); root.setStyle("-fx-background-color: " + color); } - Входные данные: нажатие кнопки
- Решение:
Кнопка с задержкой: Создайте кнопку, которая временно отключает себя на 3 секунды после нажатия.
- Решение:java
@FXML public void handleDelayButtonClick() { button.setDisable(true); PauseTransition pause = new PauseTransition(Duration.seconds(3)); pause.setOnFinished(event -> button.setDisable(false)); pause.play(); } - Входные данные: нажатие кнопки
- Решение:
Кнопка с переключением состояния: Создайте кнопку, которая меняет текст на "Включено" / "Выключено" при каждом нажатии.
- Решение:java
private boolean isOn = false; @FXML public void handleToggleButtonClick() { isOn = !isOn; button.setText(isOn ? "Включено" : "Выключено"); } - Входные данные: нажатие кнопки
- Решение:
Кнопка для переключения видимости метки: Создайте кнопку, которая скрывает или показывает метку.
- Решение:java
@FXML public void handleToggleLabelVisibilityButtonClick() { label.setVisible(!label.isVisible()); } - Входные данные: нажатие кнопки
- Решение:
Кнопка для сброса текста: Создайте кнопку, которая сбрасывает текст метки на "По умолчанию".
- Решение:java
@FXML public void handleResetLabelButtonClick() { label.setText("По умолчанию"); } - Входные данные: нажатие кнопки
- Решение:
Кнопка для добавления текста: Создайте кнопку, которая добавляет текст в конец метки.
- Решение:java
@FXML public void handleAddTextButtonClick() { label.setText(label.getText() + " Добавлено"); } - Входные данные: нажатие кнопки
- Решение:
Кнопка для загрузки файла: Создайте кнопку, которая открывает диалоговое окно для выбора файла.
- Решение:java
@FXML public void handleLoadFileButtonClick() { FileChooser fileChooser = new FileChooser(); File file = fileChooser.showOpenDialog(stage); if (file != null) { label.setText("Выбранный файл: " + file.getName()); } } - Входные данные: нажатие кнопки
- Решение:
Кнопка для смены шрифта: Создайте кнопку, которая меняет шрифт метки.
- Решение:java
@FXML public void handleChangeFontButtonClick() { label.setFont(new Font("Arial", 24)); } - Входные данные: нажатие кнопки
- Решение:
Кнопка для остановки анимации: Создайте кнопку, которая останавливает анимацию другого элемента.
- Решение:java
@FXML public void handleStopAnimationButtonClick() { // Логика для остановки анимации } - Входные данные: нажатие кнопки
- Решение:
Кнопка для сохранения текста в файл: Создайте кнопку, которая сохраняет текст из метки в файл.
- Решение:java
@FXML public void handleSaveTextButtonClick() { try (PrintWriter out = new PrintWriter("output.txt")) { out.println(label.getText()); } catch (FileNotFoundException e) { e.printStackTrace(); } } - Входные данные: нажатие кнопки
- Решение:
Кнопка для генерации случайного числа: Создайте кнопку, которая генерирует и отображает случайное число в метке.
- Решение:java
@FXML public void handleGenerateRandomNumberButtonClick() { int randomNumber = (int) (Math.random() * 100); label.setText("Случайное число: " + randomNumber); } - Входные данные: нажатие кнопки
- Решение:
CHECKBOX
Базовые задачи (20)
Создание CheckBox: Создайте CheckBox для выбора согласия с условиями.
- Решение:java
@FXML private CheckBox agreeCheckBox; @FXML public void handleCheckBoxAction() { if (agreeCheckBox.isSelected()) { label.setText("Согласен с условиями"); } else { label.setText("Не согласен с условиями"); } } - Входные данные: изменение состояния CheckBox
- Решение:
Счетчик CheckBox: Создайте несколько CheckBox, которые подсчитывают, сколько из них выбрано.
- Решение:java
@FXML private CheckBox checkBox1, checkBox2, checkBox3; @FXML public void handleCheckBoxAction() { int count = 0; if (checkBox1.isSelected()) count++; if (checkBox2.isSelected()) count++; if (checkBox3.isSelected()) count++; label.setText("Выбрано: " + count); } - Входные данные: изменение состояния любого CheckBox
- Решение:
CheckBox для выбора нескольких опций: Создайте CheckBox для выбора нескольких языков.
- Решение:java
@FXML public void handleLanguagesCheckBoxAction() { StringBuilder selectedLanguages = new StringBuilder("Выбрано: "); if (englishCheckBox.isSelected()) selectedLanguages.append("Английский "); if (spanishCheckBox.isSelected()) selectedLanguages.append("Испанский "); label.setText(selectedLanguages.toString()); } - Входные данные: изменение состояния любого CheckBox
- Решение:
CheckBox для включения/выключения: Создайте CheckBox для включения и выключения метки.
- Решение:java
@FXML public void handleToggleLabelCheckBox() { label.setVisible(agreeCheckBox.isSelected()); } - Входные данные: изменение состояния CheckBox
- Решение:
CheckBox для выбора формата: Создайте CheckBox для выбора формата вывода (текст/число).
- Решение:java
@FXML public void handleFormatCheckBox() { if (textFormatCheckBox.isSelected()) { label.setText("Формат: Текст"); } else { label.setText("Формат: Число"); } } - Входные данные: изменение состояния CheckBox
- Решение:
CheckBox с событием: Создайте CheckBox, который меняет цвет фона, когда он выбран.
- Решение:java
@FXML public void handleColorChangeCheckBox() { if (colorCheckBox.isSelected()) { root.setStyle("-fx-background-color: yellow;"); } else { root.setStyle(""); } } - Входные данные: изменение состояния CheckBox
- Решение:
Сохранение состояния CheckBox: Создайте CheckBox, который сохраняет свое состояние при закрытии приложения.
- Решение:java
@FXML public void handleCheckBoxAction() { Preferences prefs = Preferences.userNodeForPackage(this.getClass()); prefs.putBoolean("checkBoxState", agreeCheckBox.isSelected()); } - Входные данные: изменение состояния CheckBox
- Решение:
CheckBox для выбора уровня сложности: Создайте CheckBox для выбора уровня сложности игры.
- Решение:java
@FXML public void handleDifficultyCheckBox() { if (easyCheckBox.isSelected()) { label.setText("Уровень сложности: Легкий"); } else { label.setText("Уровень сложности: Тяжелый"); } } - Входные данные: изменение состояния CheckBox
- Решение:
CheckBox для выбора транспорта: Создайте CheckBox для выбора видов транспорта (Автомобиль, Велосипед, Мотоцикл).
- Решение:java
@FXML public void handleTransportCheckBox() { StringBuilder selectedTransport = new StringBuilder("Выбрано: "); if (carCheckBox.isSelected()) selectedTransport.append("Автомобиль "); if (bikeCheckBox.isSelected()) selectedTransport.append("Велосипед "); if (motorcycleCheckBox.isSelected()) selectedTransport.append("Мотоцикл "); label.setText(selectedTransport.toString()); } - Входные данные: изменение состояния любого CheckBox
- Решение:
CheckBox для настройки предпочтений: Создайте CheckBox для настройки предпочтений (Уведомления, Темная тема).
- Решение:java
@FXML public void handlePreferencesCheckBox() { StringBuilder preferences = new StringBuilder("Настройки: "); if (notificationsCheckBox.isSelected()) preferences.append("Уведомления включены "); if (darkThemeCheckBox.isSelected()) preferences.append("Темная тема включена "); label.setText(preferences.toString()); } - Входные данные: изменение состояния любого CheckBox
- Решение:
CheckBox для выбора увлечений: Создайте CheckBox для выбора увлечений (Чтение, Спорт, Музыка).
- Решение:java
@FXML public void handleHobbiesCheckBox() { StringBuilder selectedHobbies = new StringBuilder("Увлечения: "); if (readingCheckBox.isSelected()) selectedHobbies.append("Чтение "); if (sportsCheckBox.isSelected()) selectedHobbies.append("Спорт "); if (musicCheckBox.isSelected()) selectedHobbies.append("Музыка "); label.setText(selectedHobbies.toString()); } - Входные данные: изменение состояния любого CheckBox
- Решение:
Смена языка через CheckBox: Создайте CheckBox для переключения языков интерфейса.
- Решение:java
@FXML public void handleLanguageCheckBox() { if (russianCheckBox.isSelected()) { label.setText("Выбран русский язык"); } else { label.setText("Выбран английский язык"); } } - Входные данные: изменение состояния CheckBox
- Решение:
CheckBox для выбора инструментов: Создайте CheckBox для выбора инструментов разработки (Java, Python, C++).
- Решение:java
@FXML public void handleToolsCheckBox() { StringBuilder selectedTools = new StringBuilder("Инструменты: "); if (javaCheckBox.isSelected()) selectedTools.append("Java "); if (pythonCheckBox.isSelected()) selectedTools.append("Python "); if (cppCheckBox.isSelected()) selectedTools.append("C++ "); label.setText(selectedTools.toString()); } - Входные данные: изменение состояния любого CheckBox
- Решение:
CheckBox для выбора форматов файлов: Создайте CheckBox для выбора форматов файлов (JPEG, PNG, GIF).
- Решение:java
@FXML public void handleFileFormatsCheckBox() { StringBuilder selectedFormats = new StringBuilder("Форматы: "); if (jpegCheckBox.isSelected()) selectedFormats.append("JPEG "); if (pngCheckBox.isSelected()) selectedFormats.append("PNG "); if (gifCheckBox.isSelected()) selectedFormats.append("GIF "); label.setText(selectedFormats.toString()); } - Входные данные: изменение состояния любого CheckBox
- Решение:
CheckBox для выбора инструментов для рисования: Создайте CheckBox для выбора инструментов для рисования (Кисть, Ластик, Ручка).
- Решение:java
@FXML public void handleDrawingToolsCheckBox() { StringBuilder selectedTools = new StringBuilder("Инструменты: "); if (brushCheckBox.isSelected()) selectedTools.append("Кисть "); if (eraserCheckBox.isSelected()) selectedTools.append("Ластик "); if (penCheckBox.isSelected()) selectedTools.append("Ручка "); label.setText(selectedTools.toString()); } - Входные данные: изменение состояния любого CheckBox
- Решение:
CheckBox для выбора любимых блюд: Создайте CheckBox для выбора любимых блюд (Пицца, Суши, Бургер).
- Решение:java
@FXML public void handleFoodCheckBox() { StringBuilder selectedFoods = new StringBuilder("Блюда: "); if (pizzaCheckBox.isSelected()) selectedFoods.append("Пицца "); if (sushiCheckBox.isSelected()) selectedFoods.append("Суши "); if (burgerCheckBox.isSelected()) selectedFoods.append("Бургер "); label.setText(selectedFoods.toString()); } - Входные данные: изменение состояния любого CheckBox
- Решение:
CheckBox для настройки параметров игры: Создайте CheckBox для настройки параметров игры (Звук, Вибрация).
- Решение:java
@FXML public void handleGameSettingsCheckBox() { StringBuilder settings = new StringBuilder("Настройки игры: "); if (soundCheckBox.isSelected()) settings.append("Звук включен "); if (vibrationCheckBox.isSelected()) settings.append("Вибрация включена "); label.setText(settings.toString()); } - Входные данные: изменение состояния любого CheckBox
- Решение:
CheckBox для выбора музыки: Создайте CheckBox для выбора музыки (Поп, Рок, Джаз).
- Решение:java
@FXML public void handleMusicGenresCheckBox() { StringBuilder selectedGenres = new StringBuilder("Жанры музыки: "); if (popCheckBox.isSelected()) selectedGenres.append("Поп "); if (rockCheckBox.isSelected()) selectedGenres.append("Рок "); if (jazzCheckBox.isSelected()) selectedGenres.append("Джаз "); label.setText(selectedGenres.toString()); } - Входные данные: изменение состояния любого CheckBox
- Решение:
CheckBox для выбора сценария: Создайте CheckBox для выбора сценария (Работа, Учеба, Развлечение).
- Решение:java
@FXML public void handleScenarioCheckBox() { StringBuilder selectedScenarios = new StringBuilder("Сценарий: "); if (workCheckBox.isSelected()) selectedScenarios.append("Работа "); if (studyCheckBox.isSelected()) selectedScenarios.append("Учеба "); if (entertainmentCheckBox.isSelected()) selectedScenarios.append("Развлечение "); label.setText(selectedScenarios.toString()); } - Входные данные: изменение состояния любого CheckBox
- Решение:
CheckBox для выбора местоположения: Создайте CheckBox для выбора местоположения (Город, Село, Деревня).
- Решение:java
@FXML public void handleLocationCheckBox() { StringBuilder selectedLocations = new StringBuilder("Местоположение: "); if (cityCheckBox.isSelected()) selectedLocations.append("Город "); if (villageCheckBox.isSelected()) selectedLocations.append("Село "); if (hamletCheckBox.isSelected()) selectedLocations.append("Деревня "); label.setText(selectedLocations.toString()); } - Входные данные: изменение состояния любого CheckBox
- Решение:
TOGGLEBUTTON
Базовые задачи (20)
Создание ToggleButton: Создайте ToggleButton, который меняет текст на "Включено"/"Выключено".
- Решение:java
@FXML private ToggleButton toggleButton; @FXML public void handleToggleButtonAction() { if (toggleButton.isSelected()) { label.setText("Включено"); } else { label.setText("Выключено"); } } - Входные данные: изменение состояния ToggleButton
- Решение:
ToggleButton для переключения фонового цвета: Создайте ToggleButton, который изменяет фон на зеленый, когда он включен.
- Решение:java
@FXML public void handleToggleButtonColorAction() { if (toggleButton.isSelected()) { root.setStyle("-fx-background-color: green;"); } else { root.setStyle(""); } } - Входные данные: изменение состояния ToggleButton
- Решение:
ToggleButton для управления звуком: Создайте ToggleButton для включения и выключения звука.
- Решение:java
@FXML public void handleSoundToggleButtonAction() { if (toggleButton.isSelected()) { label.setText("Звук включен"); } else { label.setText("Звук выключен"); } } - Входные данные: изменение состояния ToggleButton
- Решение:
ToggleButton для смены языка: Создайте ToggleButton для переключения между русским и английским языками.
- Решение:java
@FXML public void handleLanguageToggleButtonAction() { if (toggleButton.isSelected()) { label.setText("Выбран русский язык"); } else { label.setText("Выбран английский язык"); } } - Входные данные: изменение состояния ToggleButton
- Решение:
ToggleButton для отображения информации: Создайте ToggleButton для показа/скрытия информации.
- Решение:java
@FXML public void handleInfoToggleButtonAction() { infoLabel.setVisible(toggleButton.isSelected()); } - Входные данные: изменение состояния ToggleButton
- Решение:
ToggleButton для активации режима: Создайте ToggleButton для включения режима редактирования.
- Решение:java
@FXML public void handleEditModeToggleButtonAction() { if (toggleButton.isSelected()) { label.setText("Режим редактирования включен"); } else { label.setText("Режим редактирования выключен"); } } - Входные данные: изменение состояния ToggleButton
- Решение:
ToggleButton для смены стиля: Создайте ToggleButton для переключения стилей интерфейса (темная/светлая тема).
- Решение:java
@FXML public void handleThemeToggleButtonAction() { if (toggleButton.isSelected()) { root.setStyle("-fx-background-color: black; -fx-text-fill: white;"); } else { root.setStyle(""); } } - Входные данные: изменение состояния ToggleButton
- Решение:
ToggleButton для отображения/скрытия метки: Создайте ToggleButton для управления видимостью метки.
- Решение:java
@FXML public void handleLabelVisibilityToggleButtonAction() { label.setVisible(toggleButton.isSelected()); } - Входные данные: изменение состояния ToggleButton
- Решение:
ToggleButton для управления анимацией: Создайте ToggleButton для старта и остановки анимации.
- Решение:java
@FXML public void handleAnimationToggleButtonAction() { if (toggleButton.isSelected()) { // Логика для начала анимации } else { // Логика для остановки анимации } } - Входные данные: изменение состояния ToggleButton
- Решение:
ToggleButton для управления подсветкой текста: Создайте ToggleButton, который включает и выключает подсветку текста.
- Решение:java
@FXML public void handleHighlightToggleButtonAction() { if (toggleButton.isSelected()) { label.setStyle("-fx-background-color: yellow;"); } else { label.setStyle(""); } } - Входные данные: изменение состояния ToggleButton
- Решение:
ToggleButton для активации режима обучения: Создайте ToggleButton для включения и выключения режима обучения.
- Решение:java
@FXML public void handleTrainingModeToggleButtonAction() { if (toggleButton.isSelected()) { label.setText("Режим обучения включен"); } else { label.setText("Режим обучения выключен"); } } - Входные данные: изменение состояния ToggleButton
- Решение:
ToggleButton для активации режима игры: Создайте ToggleButton для включения и выключения режима игры.
- Решение:java
@FXML public void handleGameModeToggleButtonAction() { if (toggleButton.isSelected()) { label.setText("Режим игры включен"); } else { label.setText("Режим игры выключен"); } } - Входные данные: изменение состояния ToggleButton
- Решение:
ToggleButton для активации режима тестирования: Создайте ToggleButton для включения и выключения режима тестирования.
- Решение:java
@FXML public void handleTestModeToggleButtonAction() { if (toggleButton.isSelected()) { label.setText("Режим тестирования включен"); } else { label.setText("Режим тестирования выключен"); } } - Входные данные: изменение состояния ToggleButton
- Решение:
ToggleButton для активации режима записи: Создайте ToggleButton для включения и выключения режима записи.
- Решение:java
@FXML public void handleRecordingModeToggleButtonAction() { if (toggleButton.isSelected()) { label.setText("Режим записи включен"); } else { label.setText("Режим записи выключен"); } } - Входные данные: изменение состояния ToggleButton
- Решение:
ToggleButton для управления подсказками: Создайте ToggleButton для включения и выключения подсказок в приложении.
- Решение:java
@FXML public void handleHintsToggleButtonAction() { if (toggleButton.isSelected()) { label.setText("Подсказки включены"); } else { label.setText("Подсказки выключены"); } } - Входные данные: изменение состояния ToggleButton
- Решение:
ToggleButton для выбора режима рисования: Создайте ToggleButton для выбора режима рисования (Кисть/Ластик).
- Решение:java
@FXML public void handleDrawingModeToggleButtonAction() { if (toggleButton.isSelected()) { label.setText("Режим рисования: Кисть"); } else { label.setText("Режим рисования: Ластик"); } } - Входные данные: изменение состояния ToggleButton
- Решение:
ToggleButton для управления доступом: Создайте ToggleButton для управления доступом к функции (включено/выключено).
- Решение:java
@FXML public void handleAccessToggleButtonAction() { if (toggleButton.isSelected()) { label.setText("Доступ разрешен"); } else { label.setText("Доступ запрещен"); } } - Входные данные: изменение состояния ToggleButton
- Решение:
ToggleButton для включения режима защиты: Создайте ToggleButton для включения и выключения режима защиты.
- Решение:java
@FXML public void handleProtectionModeToggleButtonAction() { if (toggleButton.isSelected()) { label.setText("Режим защиты включен"); } else { label.setText("Режим защиты выключен"); } } - Входные данные: изменение состояния ToggleButton
- Решение:
ToggleButton для управления отображением меню: Создайте ToggleButton для показа/скрытия меню.
- Решение:java
@FXML public void handleMenuToggleButtonAction() { menu.setVisible(toggleButton.isSelected()); } - Входные данные: изменение состояния ToggleButton
- Решение:
ToggleButton для включения режима отладки: Создайте ToggleButton для включения и выключения режима отладки.
- Решение:java
@FXML public void handleDebugModeToggleButtonAction() { if (toggleButton.isSelected()) { label.setText("Режим отладки включен"); } else { label.setText("Режим отладки выключен"); } } - Входные данные: изменение состояния ToggleButton
- Решение:
JDBC
Базовые задачи (40)
Подключение к базе данных: Напишите код для подключения к базе данных MySQL.
- Решение:java
import java.sql.Connection; import java.sql.DriverManager; import java.sql.SQLException; public class DatabaseConnection { public static void main(String[] args) { String url = "jdbc:mysql://localhost:3306/your_database"; String user = "your_username"; String password = "your_password"; try (Connection connection = DriverManager.getConnection(url, user, password)) { System.out.println("Подключение успешно!"); } catch (SQLException e) { e.printStackTrace(); } } } - Входные данные: URL базы данных, имя пользователя, пароль.
- Решение:
Создание таблицы: Напишите код для создания таблицы
employees.- Решение:java
public void createTable() { String query = "CREATE TABLE employees (id INT PRIMARY KEY AUTO_INCREMENT, name VARCHAR(100), age INT)"; try (Connection connection = DriverManager.getConnection(url, user, password); Statement statement = connection.createStatement()) { statement.executeUpdate(query); System.out.println("Таблица создана!"); } catch (SQLException e) { e.printStackTrace(); } } - Входные данные: Структура таблицы.
- Решение:
Вставка данных: Напишите код для вставки данных в таблицу
employees.- Решение:java
public void insertEmployee(String name, int age) { String query = "INSERT INTO employees (name, age) VALUES (?, ?)"; try (Connection connection = DriverManager.getConnection(url, user, password); PreparedStatement preparedStatement = connection.prepareStatement(query)) { preparedStatement.setString(1, name); preparedStatement.setInt(2, age); preparedStatement.executeUpdate(); System.out.println("Данные вставлены!"); } catch (SQLException e) { e.printStackTrace(); } } - Входные данные: Имя, возраст.
- Решение:
Выборка данных: Напишите код для выборки всех данных из таблицы
employees.- Решение:java
public void selectAllEmployees() { String query = "SELECT * FROM employees"; try (Connection connection = DriverManager.getConnection(url, user, password); Statement statement = connection.createStatement(); ResultSet resultSet = statement.executeQuery(query)) { while (resultSet.next()) { System.out.println("ID: " + resultSet.getInt("id") + ", Name: " + resultSet.getString("name") + ", Age: " + resultSet.getInt("age")); } } catch (SQLException e) { e.printStackTrace(); } } - Входные данные: Нет.
- Решение:
Обновление данных: Напишите код для обновления возраста сотрудника.
- Решение:java
public void updateEmployeeAge(int id, int newAge) { String query = "UPDATE employees SET age = ? WHERE id = ?"; try (Connection connection = DriverManager.getConnection(url, user, password); PreparedStatement preparedStatement = connection.prepareStatement(query)) { preparedStatement.setInt(1, newAge); preparedStatement.setInt(2, id); preparedStatement.executeUpdate(); System.out.println("Возраст обновлен!"); } catch (SQLException e) { e.printStackTrace(); } } - Входные данные: ID сотрудника, новый возраст.
- Решение:
Удаление данных: Напишите код для удаления сотрудника из таблицы.
- Решение:java
public void deleteEmployee(int id) { String query = "DELETE FROM employees WHERE id = ?"; try (Connection connection = DriverManager.getConnection(url, user, password); PreparedStatement preparedStatement = connection.prepareStatement(query)) { preparedStatement.setInt(1, id); preparedStatement.executeUpdate(); System.out.println("Сотрудник удален!"); } catch (SQLException e) { e.printStackTrace(); } } - Входные данные: ID сотрудника.
- Решение:
Использование транзакций: Напишите код для выполнения нескольких операций в одной транзакции.
- Решение:java
public void transactionExample() { String insertQuery = "INSERT INTO employees (name, age) VALUES (?, ?)"; String updateQuery = "UPDATE employees SET age = age + 1 WHERE name = ?"; try (Connection connection = DriverManager.getConnection(url, user, password)) { connection.setAutoCommit(false); try (PreparedStatement insertStatement = connection.prepareStatement(insertQuery); PreparedStatement updateStatement = connection.prepareStatement(updateQuery)) { insertStatement.setString(1, "Alice"); insertStatement.setInt(2, 30); insertStatement.executeUpdate(); updateStatement.setString(1, "Alice"); updateStatement.executeUpdate(); connection.commit(); System.out.println("Транзакция выполнена!"); } catch (SQLException e) { connection.rollback(); e.printStackTrace(); } } catch (SQLException e) { e.printStackTrace(); } } - Входные данные: Имя, возраст.
- Решение:
Поиск по критериям: Напишите код для поиска сотрудников по имени.
- Решение:java
public void findEmployeeByName(String name) { String query = "SELECT * FROM employees WHERE name = ?"; try (Connection connection = DriverManager.getConnection(url, user, password); PreparedStatement preparedStatement = connection.prepareStatement(query)) { preparedStatement.setString(1, name); ResultSet resultSet = preparedStatement.executeQuery(); while (resultSet.next()) { System.out.println("ID: " + resultSet.getInt("id") + ", Name: " + resultSet.getString("name") + ", Age: " + resultSet.getInt("age")); } } catch (SQLException e) { e.printStackTrace(); } } - Входные данные: Имя сотрудника.
- Решение:
Проверка существования: Напишите код для проверки, существует ли сотрудник с заданным ID.
- Решение:java
public boolean employeeExists(int id) { String query = "SELECT COUNT(*) FROM employees WHERE id = ?"; try (Connection connection = DriverManager.getConnection(url, user, password); PreparedStatement preparedStatement = connection.prepareStatement(query)) { preparedStatement.setInt(1, id); ResultSet resultSet = preparedStatement.executeQuery(); if (resultSet.next()) { return resultSet.getInt(1) > 0; } } catch (SQLException e) { e.printStackTrace(); } return false; } - Входные данные: ID сотрудника.
- Решение:
Получение статистики: Напишите код для получения средней возраста сотрудников.
- Решение:java
public double getAverageAge() { String query = "SELECT AVG(age) FROM employees"; try (Connection connection = DriverManager.getConnection(url, user, password); Statement statement = connection.createStatement(); ResultSet resultSet = statement.executeQuery(query)) { if (resultSet.next()) { return resultSet.getDouble(1); } } catch (SQLException e) { e.printStackTrace(); } return 0; } - Входные данные: Нет.
- Решение:
Получение всех имен: Напишите код для получения всех имен сотрудников.
- Решение:java
public List<String> getAllEmployeeNames() { List<String> names = new ArrayList<>(); String query = "SELECT name FROM employees"; try (Connection connection = DriverManager.getConnection(url, user, password); Statement statement = connection.createStatement(); ResultSet resultSet = statement.executeQuery(query)) { while (resultSet.next()) { names.add(resultSet.getString("name")); } } catch (SQLException e) { e.printStackTrace(); } return names; } - Входные данные: Нет.
- Решение:
Поиск по возрасту: Напишите код для поиска сотрудников по возрасту.
- Решение:java
public void findEmployeesByAge(int age) { String query = "SELECT * FROM employees WHERE age = ?"; try (Connection connection = DriverManager.getConnection(url, user, password); PreparedStatement preparedStatement = connection.prepareStatement(query)) { preparedStatement.setInt(1, age); ResultSet resultSet = preparedStatement.executeQuery(); while (resultSet.next()) { System.out.println("ID: " + resultSet.getInt("id") + ", Name: " + resultSet.getString("name") + ", Age: " + resultSet.getInt("age")); } } catch (SQLException e) { e.printStackTrace(); } } - Входные данные: Возраст.
- Решение:
Печать всех сотрудников: Напишите код для вывода всех сотрудников в консоль.
- Решение:java
public void printAllEmployees() { String query = "SELECT * FROM employees"; try (Connection connection = DriverManager.getConnection(url, user, password); Statement statement = connection.createStatement(); ResultSet resultSet = statement.executeQuery(query)) { while (resultSet.next()) { System.out.println("ID: " + resultSet.getInt("id") + ", Name: " + resultSet.getString("name") + ", Age: " + resultSet.getInt("age")); } } catch (SQLException e) { e.printStackTrace(); } } - Входные данные: Нет.
- Решение:
Сортировка сотрудников: Напишите код для сортировки сотрудников по возрасту.
- Решение:java
public void sortEmployeesByAge() { String query = "SELECT * FROM employees ORDER BY age"; try (Connection connection = DriverManager.getConnection(url, user, password); Statement statement = connection.createStatement(); ResultSet resultSet = statement.executeQuery(query)) { while (resultSet.next()) { System.out.println("ID: " + resultSet.getInt("id") + ", Name: " + resultSet.getString("name") + ", Age: " + resultSet.getInt("age")); } } catch (SQLException e) { e.printStackTrace(); } } - Входные данные: Нет.
- Решение:
Группировка по возрасту: Напишите код для группировки сотрудников по возрасту.
- Решение:java
public void groupEmployeesByAge() { String query = "SELECT age, COUNT(*) FROM employees GROUP BY age"; try (Connection connection = DriverManager.getConnection(url, user, password); Statement statement = connection.createStatement(); ResultSet resultSet = statement.executeQuery(query)) { while (resultSet.next()) { System.out.println("Age: " + resultSet.getInt("age") + ", Count: " + resultSet.getInt(2)); } } catch (SQLException e) { e.printStackTrace(); } } - Входные данные: Нет.
- Решение:
Получение данных по диапазону: Напишите код для получения сотрудников по диапазону возраста.
- Решение:java
public void findEmployeesByAgeRange(int minAge, int maxAge) { String query = "SELECT * FROM employees WHERE age BETWEEN ? AND ?"; try (Connection connection = DriverManager.getConnection(url, user, password); PreparedStatement preparedStatement = connection.prepareStatement(query)) { preparedStatement.setInt(1, minAge); preparedStatement.setInt(2, maxAge); ResultSet resultSet = preparedStatement.executeQuery(); while (resultSet.next()) { System.out.println("ID: " + resultSet.getInt("id") + ", Name: " + resultSet.getString("name") + ", Age: " + resultSet.getInt("age")); } } catch (SQLException e) { e.printStackTrace(); } } - Входные данные: Минимальный и максимальный возраст.
- Решение:
Вставка нескольких сотрудников: Напишите код для вставки нескольких сотрудников.
- Решение:java
public void insertMultipleEmployees(List<String> names, List<Integer> ages) { String query = "INSERT INTO employees (name, age) VALUES (?, ?)"; try (Connection connection = DriverManager.getConnection(url, user, password); PreparedStatement preparedStatement = connection.prepareStatement(query)) { for (int i = 0; i < names.size(); i++) { preparedStatement.setString(1, names.get(i)); preparedStatement.setInt(2, ages.get(i)); preparedStatement.executeUpdate(); } System.out.println("Несколько сотрудников вставлены!"); } catch (SQLException e) { e.printStackTrace(); } } - Входные данные: Список имен, список возрастов.
- Решение:
Удаление всех сотрудников: Напишите код для удаления всех сотрудников из таблицы.
- Решение:java
public void deleteAllEmployees() { String query = "DELETE FROM employees"; try (Connection connection = DriverManager.getConnection(url, user, password); Statement statement = connection.createStatement()) { statement.executeUpdate(query); System.out.println("Все сотрудники удалены!"); } catch (SQLException e) { e.printStackTrace(); } } - Входные данные: Нет.
- Решение:
Добавление уникального ограничения: Напишите код для добавления уникального ограничения на имя сотрудника.
- Решение:java
public void addUniqueConstraint() { String query = "ALTER TABLE employees ADD CONSTRAINT unique_name UNIQUE (name)"; try (Connection connection = DriverManager.getConnection(url, user, password); Statement statement = connection.createStatement()) { statement.executeUpdate(query); System.out.println("Уникальное ограничение добавлено!"); } catch (SQLException e) { e.printStackTrace(); } } - Входные данные: Нет.
- Решение:
Получение данных в формате JSON: Напишите код для получения данных сотрудников в формате JSON.
- Решение:java
public String getEmployeesAsJson() { StringBuilder json = new StringBuilder("["); String query = "SELECT * FROM employees"; try (Connection connection = DriverManager.getConnection(url, user, password); Statement statement = connection.createStatement(); ResultSet resultSet = statement.executeQuery(query)) { while (resultSet.next()) { json.append("{") .append("\"id\":").append(resultSet.getInt("id")).append(",") .append("\"name\":\"").append(resultSet.getString("name")).append("\",") .append("\"age\":").append(resultSet.getInt("age")) .append("},"); } if (json.length() > 1) { json.deleteCharAt(json.length() - 1); // Удаление последней запятой } json.append("]"); } catch (SQLException e) { e.printStackTrace(); } return json.toString(); } - Входные данные: Нет.
- Решение:
Сложные задачи (10)
Подключение с использованием пула соединений: Реализуйте пул соединений для работы с базой данных.
- Решение:java
import javax.sql.DataSource; import com.zaxxer.hikari.HikariConfig; import com.zaxxer.hikari.HikariDataSource; public class ConnectionPool { private static DataSource dataSource; static { HikariConfig config = new HikariConfig(); config.setJdbcUrl("jdbc:mysql://localhost:3306/your_database"); config.setUsername("your_username"); config.setPassword("your_password"); config.setMaximumPoolSize(10); dataSource = new HikariDataSource(config); } public static Connection getConnection() throws SQLException { return dataSource.getConnection(); } } - Входные данные: URL базы данных, имя пользователя, пароль.
- Решение:
Сохранение данных в формате CSV: Напишите код для сохранения данных сотрудников в файл CSV.
- Решение:java
public void saveEmployeesToCsv(String filePath) { String query = "SELECT * FROM employees"; try (Connection connection = DriverManager.getConnection(url, user, password); Statement statement = connection.createStatement(); ResultSet resultSet = statement.executeQuery(query); PrintWriter writer = new PrintWriter(new File(filePath))) { writer.println("ID,Name,Age"); while (resultSet.next()) { writer.println(resultSet.getInt("id") + "," + resultSet.getString("name") + "," + resultSet.getInt("age")); } System.out.println("Данные сохранены в CSV!"); } catch (SQLException | FileNotFoundException e) { e.printStackTrace(); } } - Входные данные: Путь к файлу.
- Решение:
Импорт данных из CSV: Напишите код для импорта данных сотрудников из файла CSV.
- Решение:java
public void importEmployeesFromCsv(String filePath) { String query = "INSERT INTO employees (name, age) VALUES (?, ?)"; try (Connection connection = DriverManager.getConnection(url, user, password); PreparedStatement preparedStatement = connection.prepareStatement(query); BufferedReader br = new BufferedReader(new FileReader(filePath))) { String line; while ((line = br.readLine()) != null) { String[] values = line.split(","); preparedStatement.setString(1, values[1]); preparedStatement.setInt(2, Integer.parseInt(values[2])); preparedStatement.executeUpdate(); } System.out.println("Данные импортированы из CSV!"); } catch (SQLException | IOException e) { e.printStackTrace(); } } - Входные данные: Путь к файлу.
- Решение:
Проверка целостности данных: Напишите код для проверки целостности данных в таблице.
- Решение:java
public void checkDataIntegrity() { String query = "SELECT COUNT(*) AS count FROM employees WHERE name IS NULL OR age IS NULL"; try (Connection connection = DriverManager.getConnection(url, user, password); Statement statement = connection.createStatement(); ResultSet resultSet = statement.executeQuery(query)) { if (resultSet.next() && resultSet.getInt("count") > 0) { System.out.println("Найдены некорректные данные!"); } else { System.out.println("Целостность данных сохранена!"); } } catch (SQLException e) { e.printStackTrace(); } } - Входные данные: Нет.
- Решение:
Создание триггера: Напишите SQL-запрос для создания триггера, который будет автоматически обновлять возраст при каждом вставке.
- Решение:sql
CREATE TRIGGER update_age BEFORE INSERT ON employees FOR EACH ROW SET NEW.age = 30; -- Например, фиксированный возраст для примера - Входные данные: Нет.
- Решение:
Создание представления: Напишите SQL-запрос для создания представления, отображающего только старших сотрудников (например, старше 40 лет).
- Решение:sql
CREATE VIEW senior_employees AS SELECT * FROM employees WHERE age > 40; - Входные данные: Нет.
- Решение:
Создание процедуры: Напишите хранимую процедуру для получения всех сотрудников по возрасту.
- Решение:sql
CREATE PROCEDURE GetEmployeesByAge(IN ageParam INT) BEGIN SELECT * FROM employees WHERE age = ageParam; END; - Входные данные: Возраст.
- Решение:
Сложный запрос: Напишите SQL-запрос для получения самого молодого и самого старшего сотрудников.
- Решение:sql
SELECT MIN(age) AS youngest, MAX(age) AS oldest FROM employees; - Входные данные: Нет.
- Решение:
Сохранение состояния: Напишите код для сохранения текущего состояния таблицы в другую таблицу.
- Решение:java
public void saveState() { String query = "INSERT INTO employees_backup SELECT * FROM employees"; try (Connection connection = DriverManager.getConnection(url, user, password); Statement statement = connection.createStatement()) { statement.executeUpdate(query); System.out.println("Состояние сохранено!"); } catch (SQLException e) { e.printStackTrace(); } } - Входные данные: Нет.
- Решение:
Объединение данных из нескольких таблиц: Напишите SQL-запрос для объединения данных из двух таблиц.
- Решение:sql
SELECT e.id, e.name, d.department_name FROM employees e JOIN departments d ON e.department_id = d.id; - Входные данные: Нет.
- Решение:
MYSQL
Базовые задачи (40)
Создание базы данных: Напишите SQL-запрос для создания базы данных
company.- Решение:sql
CREATE DATABASE company;
- Решение:
Использование базы данных: Напишите SQL-запрос для использования базы данных
company.- Решение:sql
USE company;
- Решение:
Создание таблицы: Напишите SQL-запрос для создания таблицы
departments.- Решение:sql
CREATE TABLE departments ( id INT PRIMARY KEY AUTO_INCREMENT, department_name VARCHAR(100) );
- Решение:
Вставка данных в таблицу: Напишите SQL-запрос для вставки данных в таблицу
departments.- Решение:sql
INSERT INTO departments (department_name) VALUES ('HR'), ('IT'), ('Finance');
- Решение:
Выборка данных из таблицы: Напишите SQL-запрос для выборки всех данных из таблицы
departments.- Решение:sql
SELECT * FROM departments;
- Решение:
Обновление данных в таблице: Напишите SQL-запрос для обновления имени отдела.
- Решение:sql
UPDATE departments SET department_name = 'Human Resources' WHERE department_name = 'HR';
- Решение:
Удаление данных из таблицы: Напишите SQL-запрос для удаления отдела.
- Решение:sql
DELETE FROM departments WHERE department_name = 'Finance';
- Решение:
Создание внешнего ключа: Напишите SQL-запрос для добавления внешнего ключа в таблицу
employees, ссылающегося наdepartments.- Решение:sql
ALTER TABLE employees ADD department_id INT; ALTER TABLE employees ADD FOREIGN KEY (department_id) REFERENCES departments(id);
- Решение:
Создание индекса: Напишите SQL-запрос для создания индекса по колонке
nameв таблицеemployees.- Решение:sql
CREATE INDEX idx_name ON employees(name);
- Решение:
Получение всех отделов: Напишите SQL-запрос для получения всех отделов с количеством сотрудников в каждом.
- Решение:sql
SELECT d.department_name, COUNT(e.id) AS employee_count FROM departments d LEFT JOIN employees e ON d.id = e.department_id GROUP BY d.department_name;
- Решение:
Создание уникального индекса: Напишите SQL-запрос для создания уникального индекса на
nameв таблицеemployees.- Решение:sql
CREATE UNIQUE INDEX unique_name ON employees(name);
- Решение:
Группировка данных: Напишите SQL-запрос для группировки сотрудников по отделам.
- Решение:sql
SELECT d.department_name, COUNT(e.id) AS employee_count FROM departments d JOIN employees e ON d.id = e.department_id GROUP BY d.department_name;
- Решение:
Сортировка данных: Напишите SQL-запрос для получения сотрудников, отсортированных по возрасту.
- Решение:sql
SELECT * FROM employees ORDER BY age;
- Решение:
Фильтрация данных: Напишите SQL-запрос для получения сотрудников старше 30 лет.
- Решение:sql
SELECT * FROM employees WHERE age > 30;
- Решение:
Соединение таблиц: Напишите SQL-запрос для получения списка сотрудников и их отделов.
- Решение:sql
SELECT e.name, d.department_name FROM employees e JOIN departments d ON e.department_id = d.id;
- Решение:
Нахождение максимального и минимального значения: Напишите SQL-запрос для нахождения самого молодого и самого старшего сотрудников.
- Решение:sql
SELECT MIN(age) AS youngest, MAX(age) AS oldest FROM employees;
- Решение:
Получение средней зарплаты: Напишите SQL-запрос для получения средней зарплаты сотрудников.
- Решение:sql
SELECT AVG(salary) FROM employees;
- Решение:
Получение данных по диапазону: Напишите SQL-запрос для получения сотрудников с зарплатой от 30000 до 50000.
- Решение:sql
SELECT * FROM employees WHERE salary BETWEEN 30000 AND 50000;
- Решение:
Поиск по критериям: Напишите SQL-запрос для поиска сотрудников по имени.
- Решение:sql
SELECT * FROM employees WHERE name LIKE '%Alice%';
- Решение:
Объединение данных из нескольких таблиц: Напишите SQL-запрос для объединения данных из таблиц
employeesиdepartments.- Решение:sql
SELECT e.id, e.name, d.department_name FROM employees e LEFT JOIN departments d ON e.department_id = d.id;
- Решение:
Сложные задачи (10)
Создание триггера: Напишите SQL-запрос для создания триггера, который будет обновлять поле
last_updatedв таблицеemployeesпри каждом обновлении.- Решение:sql
CREATE TRIGGER update_last_updated BEFORE UPDATE ON employees FOR EACH ROW SET NEW.last_updated = NOW();
- Решение:
Создание представления: Напишите SQL-запрос для создания представления, которое показывает только старших сотрудников.
- Решение:sql
CREATE VIEW senior_employees AS SELECT * FROM employees WHERE age > 40;
- Решение:
Создание хранимой процедуры: Напишите SQL-запрос для создания хранимой процедуры, которая принимает имя отдела и возвращает сотрудников этого отдела.
- Решение:sql
CREATE PROCEDURE GetEmployeesByDepartment(IN departmentName VARCHAR(100)) BEGIN SELECT e.name FROM employees e JOIN departments d ON e.department_id = d.id WHERE d.department_name = departmentName; END;
- Решение:
Создание индекса для ускорения поиска: Напишите SQL-запрос для создания индекса на колонку
age.- Решение:sql
CREATE INDEX idx_age ON employees(age);
- Решение:
Создание временной таблицы: Напишите SQL-запрос для создания временной таблицы, которая будет хранить данные о текущих сотрудниках.
- Решение:sql
CREATE TEMPORARY TABLE current_employees AS SELECT * FROM employees WHERE status = 'active';
- Решение:
Обновление данных с использованием курсора: Напишите SQL-запрос для обновления зарплат сотрудников с использованием курсора.
- Решение:sql
DELIMITER // CREATE PROCEDURE UpdateSalaries() BEGIN DECLARE done INT DEFAULT FALSE; DECLARE emp_id INT; DECLARE emp_salary DECIMAL(10, 2); DECLARE cur CURSOR FOR SELECT id, salary FROM employees; DECLARE CONTINUE HANDLER FOR NOT FOUND SET done = TRUE; OPEN cur; read_loop: LOOP FETCH cur INTO emp_id, emp_salary; IF done THEN LEAVE read_loop; END IF; UPDATE employees SET salary = emp_salary * 1.1 WHERE id = emp_id; -- Увеличение на 10% END LOOP; CLOSE cur; END// DELIMITER ;
- Решение:
Сохранение состояния: Напишите SQL-запрос для сохранения текущего состояния таблицы в другую таблицу.
- Решение:sql
CREATE TABLE employees_backup AS SELECT * FROM employees;
- Решение:
Создание ограничений: Напишите SQL-запрос для добавления ограничения, которое запрещает вставку записей с отрицательными значениями зарплаты.
- Решение:sql
ALTER TABLE employees ADD CONSTRAINT chk_salary CHECK (salary >= 0);
- Решение:
Проверка целостности данных: Напишите SQL-запрос для проверки целостности данных в таблице.
- Решение:sql
SELECT COUNT(*) AS count FROM employees WHERE name IS NULL OR age IS NULL;
- Решение:
Создание сложного представления: Напишите SQL-запрос для создания сложного представления, которое объединяет данные из нескольких таблиц.
- Решение:sql
CREATE VIEW employee_details AS SELECT e.name, e.age, d.department_name, e.salary FROM employees e JOIN departments d ON e.department_id = d.id;
- Решение:
ВВЕДЕНИЕ В СЕРВЛЕТЫ
Базовые задачи (30)
Создание простого сервлета: Напишите сервлет, который выводит "Hello, World!".
- Решение:java
import java.io.IOException; import javax.servlet.ServletException; import javax.servlet.annotation.WebServlet; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; @WebServlet("/hello") public class HelloWorldServlet extends HttpServlet { protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { response.setContentType("text/html"); response.getWriter().println("<h1>Hello, World!</h1>"); } } - Входные данные: Нет.
- Решение:
Вывод текущей даты и времени: Напишите сервлет, который выводит текущую дату и время.
- Решение:java
import java.io.IOException; import java.text.SimpleDateFormat; import java.util.Date; import javax.servlet.ServletException; import javax.servlet.annotation.WebServlet; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; @WebServlet("/datetime") public class DateTimeServlet extends HttpServlet { protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { response.setContentType("text/html"); SimpleDateFormat formatter = new SimpleDateFormat("dd-MM-yyyy HH:mm:ss"); Date date = new Date(); response.getWriter().println("<h1>Current Date and Time: " + formatter.format(date) + "</h1>"); } } - Входные данные: Нет.
- Решение:
Получение параметров запроса: Напишите сервлет, который получает параметр
nameи выводит "Hello, [name]!".- Решение:java
import java.io.IOException; import javax.servlet.ServletException; import javax.servlet.annotation.WebServlet; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; @WebServlet("/greet") public class GreetServlet extends HttpServlet { protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { String name = request.getParameter("name"); response.setContentType("text/html"); response.getWriter().println("<h1>Hello, " + name + "!</h1>"); } } - Входные данные: Параметр
nameв URL (например,?name=Alice).
- Решение:
Формирование HTML-формы: Напишите сервлет, который выводит HTML-форму для ввода имени.
- Решение:java
import java.io.IOException; import javax.servlet.ServletException; import javax.servlet.annotation.WebServlet; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; @WebServlet("/form") public class FormServlet extends HttpServlet { protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { response.setContentType("text/html"); response.getWriter().println("<form action='greet' method='get'>"); response.getWriter().println("Name: <input type='text' name='name'/>"); response.getWriter().println("<input type='submit' value='Greet'/>"); response.getWriter().println("</form>"); } } - Входные данные: Нет.
- Решение:
Переадресация на другой сервлет: Напишите сервлет, который перенаправляет на сервлет
greet.- Решение:java
import java.io.IOException; import javax.servlet.ServletException; import javax.servlet.annotation.WebServlet; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; @WebServlet("/redirect") public class RedirectServlet extends HttpServlet { protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { response.sendRedirect("greet?name=Bob"); } } - Входные данные: Нет.
- Решение:
Перенаправление запроса: Напишите сервлет, который перенаправляет запрос на другой сервлет.
- Решение:java
import java.io.IOException; import javax.servlet.ServletException; import javax.servlet.annotation.WebServlet; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; @WebServlet("/forward") public class ForwardServlet extends HttpServlet { protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { request.getRequestDispatcher("greet?name=Charlie").forward(request, response); } } - Входные данные: Нет.
- Решение:
Настройка web.xml: Добавьте маппинг для сервлета
HelloWorldServletв web.xml.- Решение:xml
<servlet> <servlet-name>HelloWorldServlet</servlet-name> <servlet-class>com.example.HelloWorldServlet</servlet-class> </servlet> <servlet-mapping> <servlet-name>HelloWorldServlet</servlet-name> <url-pattern>/hello</url-pattern> </servlet-mapping>
- Решение:
Передача параметров инициализации: Настройте параметр инициализации для сервлета.
- Решение:xml
<servlet> <servlet-name>ConfigServlet</servlet-name> <servlet-class>com.example.ConfigServlet</servlet-class> <init-param> <param-name>param1</param-name> <param-value>value1</param-value> </init-param> </servlet>
- Решение:
Обработка ошибок: Настройте обработчик ошибок для сервлета.
- Решение:xml
<error-page> <error-code>404</error-code> <location>/error</location> </error-page>
- Решение:
Создание куки: Напишите сервлет, который создает куки.
- Решение:java
import java.io.IOException; import javax.servlet.ServletException; import javax.servlet.annotation.WebServlet; import javax.servlet.http.Cookie; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; @WebServlet("/setcookie") public class CookieServlet extends HttpServlet { protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { Cookie cookie = new Cookie("username", "JohnDoe"); response.addCookie(cookie); response.getWriter().println("Cookie set: " + cookie.getName() + "=" + cookie.getValue()); } } - Входные данные: Нет.
- Решение:
Чтение куки: Напишите сервлет, который читает куки.
- Решение:java
import java.io.IOException; import javax.servlet.ServletException; import javax.servlet.annotation.WebServlet; import javax.servlet.http.Cookie; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; @WebServlet("/getcookie") public class ReadCookieServlet extends HttpServlet { protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { Cookie[] cookies = request.getCookies(); for (Cookie cookie : cookies) { if ("username".equals(cookie.getName())) { response.getWriter().println("Cookie value: " + cookie.getValue()); } } } } - Входные данные: Нет.
- Решение:
Создание сессии: Напишите сервлет, который создает сессию и сохраняет в ней имя пользователя.
- Решение:java
import java.io.IOException; import javax.servlet.ServletException; import javax.servlet.annotation.WebServlet; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import javax.servlet.http.HttpSession; @WebServlet("/createsession") public class SessionServlet extends HttpServlet { protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { HttpSession session = request.getSession(); session.setAttribute("username", "JohnDoe"); response.getWriter().println("Session created and username set."); } } - Входные данные: Нет.
- Решение:
Чтение данных из сессии: Напишите сервлет, который читает имя пользователя из сессии.
- Решение:java
import java.io.IOException; import javax.servlet.ServletException; import javax.servlet.annotation.WebServlet; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import javax.servlet.http.HttpSession; @WebServlet("/readsess") public class ReadSessionServlet extends HttpServlet { protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { HttpSession session = request.getSession(); String username = (String) session.getAttribute("username"); response.getWriter().println("Username from session: " + username); } } - Входные данные: Нет.
- Решение:
Уничтожение сессии: Напишите сервлет, который уничтожает сессию.
- Решение:java
import java.io.IOException; import javax.servlet.ServletException; import javax.servlet.annotation.WebServlet; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; @WebServlet("/destroysess") public class DestroySessionServlet extends HttpServlet { protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { request.getSession().invalidate(); response.getWriter().println("Session destroyed."); } } - Входные данные: Нет.
- Решение:
Установка времени жизни куки: Напишите сервлет, который устанавливает время жизни куки.
- Решение:java
import java.io.IOException; import javax.servlet.ServletException; import javax.servlet.annotation.WebServlet; import javax.servlet.http.Cookie; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; @WebServlet("/setcookieexpiry") public class CookieExpiryServlet extends HttpServlet { protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { Cookie cookie = new Cookie("sessionID", "123456"); cookie.setMaxAge(60 * 60); // 1 hour response.addCookie(cookie); response.getWriter().println("Cookie with expiry set."); } } - Входные данные: Нет.
- Решение:
Проверка наличия сессии: Напишите сервлет, который проверяет, есть ли активная сессия.
- Решение:java
import java.io.IOException; import javax.servlet.ServletException; import javax.servlet.annotation.WebServlet; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import javax.servlet.http.HttpSession; @WebServlet("/checksession") public class CheckSessionServlet extends HttpServlet { protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { HttpSession session = request.getSession(false); if (session != null) { response.getWriter().println("Active session found."); } else { response.getWriter().println("No active session."); } } } - Входные данные: Нет.
- Решение:
Создание сервлета с инициализацией параметров: Напишите сервлет, который выводит параметры инициализации из web.xml.
- Решение:java
import java.io.IOException; import javax.servlet.ServletException; import javax.servlet.annotation.WebServlet; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; @WebServlet("/initparams") public class InitParamsServlet extends HttpServlet { protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { String param1 = getServletConfig().getInitParameter("param1"); response.getWriter().println("Init Parameter: " + param1); } } - Входные данные: Параметр
param1в web.xml.
- Решение:
Логирование ошибок в сервлете: Настройте логирование ошибок в вашем сервлете.
- Решение:java
import java.io.IOException; import java.util.logging.Level; import java.util.logging.Logger; import javax.servlet.ServletException; import javax.servlet.annotation.WebServlet; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; @WebServlet("/errorlogging") public class ErrorLoggingServlet extends HttpServlet { private static final Logger LOGGER = Logger.getLogger(ErrorLoggingServlet.class.getName()); protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { try { // Code that might throw an exception throw new IOException("Sample IOException"); } catch (IOException e) { LOGGER.log(Level.SEVERE, "Error occurred: ", e); response.getWriter().println("An error occurred. Check logs for details."); } } } - Входные данные: Нет.
- Решение:
Формирование HTML таблицы из базы данных: Напишите сервлет, который выводит данные из базы данных в виде HTML таблицы.
- Решение:java
import java.io.IOException; import java.io.PrintWriter; import java.sql.Connection; import java.sql.DriverManager; import java.sql.ResultSet; import java.sql.Statement; import javax.servlet.ServletException; import javax.servlet.annotation.WebServlet; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; @WebServlet("/dbtable") public class DatabaseTableServlet extends HttpServlet { protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { response.setContentType("text/html"); PrintWriter out = response.getWriter(); out.println("<table border='1'><tr><th>ID</th><th>Name</th></tr>"); try { Connection con = DriverManager.getConnection("jdbc:mysql://localhost:3306/mydb", "user", "password"); Statement stmt = con.createStatement(); ResultSet rs = stmt.executeQuery("SELECT id, name FROM employees"); while (rs.next()) { out.println("<tr><td>" + rs.getInt("id") + "</td><td>" + rs.getString("name") + "</td></tr>"); } out.println("</table>"); con.close(); } catch (Exception e) { out.println("Error: " + e.getMessage()); } } } - Входные данные: Подключение к базе данных.
- Решение:
Создание сервлета с защитой от CSRF: Напишите сервлет, который использует токены для защиты от CSRF.
- Решение:java
import java.io.IOException; import java.util.UUID; import javax.servlet.ServletException; import javax.servlet.annotation.WebServlet; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import javax.servlet.http.HttpSession; @WebServlet("/csrf") public class CSRFServlet extends HttpServlet { protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { HttpSession session = request.getSession(); String csrfToken = UUID.randomUUID().toString(); session.setAttribute("csrfToken", csrfToken); response.getWriter().println("<form method='post'>"); response.getWriter().println("<input type='hidden' name='csrfToken' value='" + csrfToken + "'/>"); response.getWriter().println("<input type='submit' value='Submit'/>"); response.getWriter().println("</form>"); } } - Входные данные: Нет.
- Решение:
Сложные задачи (10)
Создание фильтра для логирования: Напишите фильтр, который логирует все запросы к сервлетам.
- Решение:java
import java.io.IOException; import javax.servlet.Filter; import javax.servlet.FilterChain; import javax.servlet.FilterConfig; import javax.servlet.ServletException; import javax.servlet.ServletRequest; import javax.servlet.ServletResponse; public class LoggingFilter implements Filter { public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException { System.out.println("Request received at: " + request.getRemoteAddr()); chain.doFilter(request, response); } public void init(FilterConfig filterConfig) throws ServletException {} public void destroy() {} }
- Решение:
Создание сервлета для работы с файлами: Напишите сервлет, который загружает файл на сервер.
- Решение:java
import java.io.File; import java.io.FileOutputStream; import java.io.IOException; import javax.servlet.ServletException; import javax.servlet.annotation.MultipartConfig; import javax.servlet.annotation.WebServlet; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import javax.servlet.http.Part; @WebServlet("/upload") @MultipartConfig public class FileUploadServlet extends HttpServlet { protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { Part filePart = request.getPart("file"); File file = new File("/uploads/" + filePart.getSubmittedFileName()); try (FileOutputStream fos = new FileOutputStream(file)) { fos.write(filePart.getInputStream().readAllBytes()); } response.getWriter().println("File uploaded successfully!"); } } - Входные данные: Файл для загрузки.
- Решение:
Создание сервлета с использованием JSON: Напишите сервлет, который возвращает данные в формате JSON.
- Решение:java
import java.io.IOException; import javax.servlet.ServletException; import javax.servlet.annotation.WebServlet; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import com.google.gson.Gson; @WebServlet("/data") public class JsonServlet extends HttpServlet { protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { response.setContentType("application/json"); User user = new User("Alice", 25); String json = new Gson().toJson(user); response.getWriter().println(json); } } class User { private String name; private int age; public User(String name, int age) { this.name = name; this.age = age; } } - Входные данные: Нет.
- Решение:
Создание сервлета для работы с базой данных: Напишите сервлет, который добавляет запись в базу данных.
- Решение:java
import java.io.IOException; import java.io.PrintWriter; import java.sql.Connection; import java.sql.DriverManager; import java.sql.PreparedStatement; import javax.servlet.ServletException; import javax.servlet.annotation.WebServlet; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; @WebServlet("/addEmployee") public class AddEmployeeServlet extends HttpServlet { protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { String name = request.getParameter("name"); try (Connection con = DriverManager.getConnection("jdbc:mysql://localhost:3306/mydb", "user", "password"); PreparedStatement ps = con.prepareStatement("INSERT INTO employees (name) VALUES (?)")) { ps.setString(1, name); ps.executeUpdate(); response.getWriter().println("Employee added: " + name); } catch (Exception e) { response.getWriter().println("Error: " + e.getMessage()); } } } - Входные данные: Параметр
name.
- Решение:
Создание сервлета для отображения данных: Напишите сервлет, который отображает данные из базы данных.
- Решение:java
import java.io.IOException; import java.io.PrintWriter; import java.sql.Connection; import java.sql.DriverManager; import java.sql.ResultSet; import java.sql.Statement; import javax.servlet.ServletException; import javax.servlet.annotation.WebServlet; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; @WebServlet("/employees") public class EmployeesServlet extends HttpServlet { protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { response.setContentType("text/html"); PrintWriter out = response.getWriter(); out.println("<table border='1'><tr><th>ID</th><th>Name</th></tr>"); try { Connection con = DriverManager.getConnection("jdbc:mysql://localhost:3306/mydb", "user", "password"); Statement stmt = con.createStatement(); ResultSet rs = stmt.executeQuery("SELECT id, name FROM employees"); while (rs.next()) { out.println("<tr><td>" + rs.getInt("id") + "</td><td>" + rs.getString("name") + "</td></tr>"); } out.println("</table>"); con.close(); } catch (Exception e) { out.println("Error: " + e.getMessage()); } } } - Входные данные: Подключение к базе данных.
- Решение:
Создание сервлета для обработки форм: Напишите сервлет, который обрабатывает данные формы.
- Решение:java
import java.io.IOException; import javax.servlet.ServletException; import javax.servlet.annotation.WebServlet; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; @WebServlet("/processForm") public class ProcessFormServlet extends HttpServlet { protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { String username = request.getParameter("username"); String password = request.getParameter("password"); response.getWriter().println("Username: " + username + ", Password: " + password); } } - Входные данные: Параметры
usernameиpassword.
- Решение:
Создание сервлета для отправки электронной почты: Напишите сервлет, который отправляет электронную почту.
- Решение:java
import java.io.IOException; import javax.mail.Message; import javax.mail.MessagingException; import javax.mail.Session; import javax.mail.Transport; import javax.mail.internet.InternetAddress; import javax.mail.internet.MimeMessage; import javax.servlet.ServletException; import javax.servlet.annotation.WebServlet; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.util.Properties; @WebServlet("/sendEmail") public class EmailServlet extends HttpServlet { protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { String to = request.getParameter("to"); String subject = "Test Email"; String body = "This is a test email."; Properties properties = new Properties(); properties.put("mail.smtp.host", "smtp.example.com"); properties.put("mail.smtp.port", "587"); Session session = Session.getInstance(properties); try { MimeMessage message = new MimeMessage(session); message.setFrom(new InternetAddress("from@example.com")); message.addRecipient(Message.RecipientType.TO, new InternetAddress(to)); message.setSubject(subject); message.setText(body); Transport.send(message); response.getWriter().println("Email sent successfully!"); } catch (MessagingException e) { response.getWriter().println("Error sending email: " + e.getMessage()); } } } - Входные данные: Параметр
to.
- Решение:
Создание сервлета для работы с асинхронными запросами: Напишите сервлет, который обрабатывает асинхронные запросы.
- Решение:java
import java.io.IOException; import javax.servlet.AsyncContext; import javax.servlet.ServletException; import javax.servlet.annotation.WebServlet; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; @WebServlet(urlPatterns = "/async", asyncSupported = true) public class AsyncServlet extends HttpServlet { protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { AsyncContext asyncContext = request.startAsync(); new Thread(() -> { try { Thread.sleep(5000); // Simulate long process asyncContext.getResponse().getWriter().println("Async response after delay."); } catch (IOException | InterruptedException e) { e.printStackTrace(); } finally { asyncContext.complete(); } }).start(); } } - Входные данные: Нет.
- Решение:
Создание RESTful сервлета: Напишите сервлет, который реализует RESTful API.
- Решение:java
import java.io.IOException; import javax.servlet.ServletException; import javax.servlet.annotation.WebServlet; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import com.google.gson.Gson; @WebServlet("/api/users") public class UserApiServlet extends HttpServlet { protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { response.setContentType("application/json"); User user = new User("Alice", 30); String json = new Gson().toJson(user); response.getWriter().println(json); } } class User { private String name; private int age; public User(String name, int age) { this.name = name; this.age = age; } } - Входные данные: Нет.
- Решение:
Создание сервлета для обработки JSON запросов: Напишите сервлет, который принимает JSON запрос и обрабатывает его.
- Решение:java
import java.io.BufferedReader; import java.io.IOException; import javax.servlet.ServletException; import javax.servlet.annotation.WebServlet; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import com.google.gson.Gson; @WebServlet("/processJson") public class JsonProcessingServlet extends HttpServlet { protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { BufferedReader reader = request.getReader(); User user = new Gson().fromJson(reader, User.class); response.getWriter().println("Received user: " + user.name); } } class User { String name; int age; } - Входные данные: JSON с параметрами
nameиage.
- Решение:
1. ЧТО ТАКОЕ JSP. ПЕРВОЕ ПРИЛОЖЕНИЕ
Базовые задачи:
Создайте первую JSP-страницу, которая отображает "Hello, World!".
- Решение:jsp
<%-- hello.jsp --%> <html> <body> <h1>Hello, World!</h1> </body> </html> - Входные данные: Нет.
- Решение:
Создайте JSP-страницу, которая отображает текущее время на сервере.
- Решение:jsp
<%-- time.jsp --%> <html> <body> <h1>Current Time: <%= new java.util.Date() %></h1> </body> </html> - Входные данные: Нет.
- Решение:
Создайте JSP-страницу, которая принимает имя пользователя и отображает приветствие.
- Решение:jsp
<%-- greeting.jsp --%> <html> <body> <form action="greeting.jsp" method="get"> Enter your name: <input type="text" name="name"> <input type="submit" value="Greet"> </form> <h1> Hello, <%= request.getParameter("name") != null ? request.getParameter("name") : "Guest" %>! </h1> </body> </html> - Входные данные: Параметр
name.
- Решение:
Создайте JSP-страницу, которая отображает список чисел от 1 до 10.
- Решение:jsp
<%-- numbers.jsp --%> <html> <body> <h1>Numbers from 1 to 10:</h1> <ul> <% for (int i = 1; i <= 10; i++) { out.println("<li>" + i + "</li>"); } %> </ul> </body> </html> - Входные данные: Нет.
- Решение:
Создайте JSP-страницу, которая показывает вашу информацию (имя, возраст, город).
- Решение:jsp
<%-- info.jsp --%> <html> <body> <h1>My Information</h1> <p>Name: John Doe</p> <p>Age: 30</p> <p>City: New York</p> </body> </html> - Входные данные: Нет.
- Решение:
Создайте JSP-страницу, которая отображает простую форму для ввода данных.
- Решение:jsp
<%-- form.jsp --%> <html> <body> <form action="form.jsp" method="get"> Name: <input type="text" name="name"><br> Age: <input type="number" name="age"><br> <input type="submit" value="Submit"> </form> </body> </html> - Входные данные: Параметры
nameиage.
- Решение:
Создайте JSP-страницу, которая показывает дату в формате "день-месяц-год".
- Решение:jsp
<%-- date.jsp --%> <html> <body> <% java.text.SimpleDateFormat sdf = new java.text.SimpleDateFormat("dd-MM-yyyy"); out.println("Current Date: " + sdf.format(new java.util.Date())); %> </body> </html> - Входные данные: Нет.
- Решение:
Создайте JSP-страницу, которая принимает два числа и показывает их сумму.
- Решение:jsp
<%-- sum.jsp --%> <html> <body> <form action="sum.jsp" method="get"> Number 1: <input type="number" name="num1"><br> Number 2: <input type="number" name="num2"><br> <input type="submit" value="Add"> </form> <% String num1Str = request.getParameter("num1"); String num2Str = request.getParameter("num2"); if (num1Str != null && num2Str != null) { int sum = Integer.parseInt(num1Str) + Integer.parseInt(num2Str); out.println("Sum: " + sum); } %> </body> </html> - Входные данные: Параметры
num1иnum2.
- Решение:
Создайте JSP-страницу, которая отображает вашу любимую цитату.
- Решение:jsp
<%-- quote.jsp --%> <html> <body> <h1>Favorite Quote</h1> <p>"The only limit to our realization of tomorrow is our doubts of today." - Franklin D. Roosevelt</p> </body> </html> - Входные данные: Нет.
- Решение:
Создайте JSP-страницу, которая генерирует случайное число.
- Решение:jsp
<%-- random.jsp --%> <html> <body> <h1>Random Number: <%= (int)(Math.random() * 100) + 1 %></h1> </body> </html> - Входные данные: Нет.
- Решение:
Создайте JSP-страницу с формой, которая отправляет данные на другую JSP-страницу.
- Решение:jsp
<%-- sendData.jsp --%> <html> <body> <form action="receiveData.jsp" method="get"> Message: <input type="text" name="message"><br> <input type="submit" value="Send"> </form> </body> </html> - Входные данные: Параметр
message.
- Решение:
Создайте JSP-страницу, которая отображает список товаров.
- Решение:jsp
<%-- products.jsp --%> <html> <body> <h1>Product List</h1> <ul> <li>Product 1</li> <li>Product 2</li> <li>Product 3</li> </ul> </body> </html> - Входные данные: Нет.
- Решение:
Создайте JSP-страницу, которая принимает дату и показывает, какой день недели.
- Решение:jsp
<%-- dayOfWeek.jsp --%> <html> <body> <form action="dayOfWeek.jsp" method="get"> Enter date (yyyy-MM-dd): <input type="text" name="date"><br> <input type="submit" value="Check Day"> </form> <% String dateStr = request.getParameter("date"); if (dateStr != null) { java.time.LocalDate date = java.time.LocalDate.parse(dateStr); out.println("Day of the week: " + date.getDayOfWeek()); } %> </body> </html> - Входные данные: Параметр
date.
- Решение:
Создайте JSP-страницу с формой для выбора цвета, которая меняет фон страницы.
- Решение:jsp
<%-- colorChange.jsp --%> <html> <body style="background-color:<%= request.getParameter("color") != null ? request.getParameter("color") : "white" %>;"> <form action="colorChange.jsp" method="get"> Select color: <select name="color"> <option value="red">Red</option> <option value="green">Green</option> <option value="blue">Blue</option> </select> <input type="submit" value="Change Color"> </form> </body> </html> - Входные данные: Параметр
color.
- Решение:
Создайте JSP-страницу, которая отображает информацию о пользователе из формы.
- Решение:jsp
<%-- userInfo.jsp --%> <html> <body> <form action="userInfo.jsp" method="get"> Name: <input type="text" name="name"><br> Age: <input type="number" name="age"><br> <input type="submit" value="Submit"> </form> <% String name = request.getParameter("name"); String age = request.getParameter("age"); if (name != null && age != null) { out.println("User Information: " + name + ", Age: " + age); } %> </body> </html> - Входные данные: Параметры
nameиage.
- Решение:
Создайте JSP-страницу с формой, которая принимает два числа и показывает произведение.
- Решение:jsp
<%-- product.jsp --%> <html> <body> <form action="product.jsp" method="get"> Number 1: <input type="number" name="num1"><br> Number 2: <input type="number" name="num2"><br> <input type="submit" value="Multiply"> </form> <% String num1Str = request.getParameter("num1"); String num2Str = request.getParameter("num2"); if (num1Str != null && num2Str != null) { int product = Integer.parseInt(num1Str) * Integer.parseInt(num2Str); out.println("Product: " + product); } %> </body> </html> - Входные данные: Параметры
num1иnum2.
- Решение:
Создайте JSP-страницу, которая показывает список имен, переданных через форму.
- Решение:jsp
<%-- names.jsp --%> <html> <body> <form action="names.jsp" method="get"> Enter names (comma separated): <input type="text" name="names"><br> <input type="submit" value="Show Names"> </form> <% String namesStr = request.getParameter("names"); if (namesStr != null) { String[] names = namesStr.split(","); out.println("<ul>"); for (String name : names) { out.println("<li>" + name.trim() + "</li>"); } out.println("</ul>"); } %> </body> </html> - Входные данные: Параметр
names.
- Решение:
Создайте JSP-страницу, которая отображает таблицу с данными о пользователях.
- Решение:jsp
<%-- users.jsp --%> <html> <body> <h1>User List</h1> <table border="1"> <tr> <th>Name</th> <th>Age</th> </tr> <tr> <td>John</td> <td>30</td> </tr> <tr> <td>Jane</td> <td>25</td> </tr> </table> </body> </html> - Входные данные: Нет.
- Решение:
Создайте JSP-страницу с формой для ввода оценки и отображения результата.
- Решение:jsp
<%-- grade.jsp --%> <html> <body> <form action="grade.jsp" method="get"> Enter grade: <input type="number" name="grade"><br> <input type="submit" value="Submit"> </form> <% String gradeStr = request.getParameter("grade"); if (gradeStr != null) { int grade = Integer.parseInt(gradeStr); if (grade >= 60) { out.println("You passed!"); } else { out.println("You failed."); } } %> </body> </html> - Входные данные: Параметр
grade.
- Решение:
Создайте JSP-страницу, которая показывает случайный цвет из массива.
- Решение:jsp
<%-- randomColor.jsp --%> <html> <body> <h1>Random Color</h1> <% String[] colors = {"Red", "Green", "Blue", "Yellow", "Pink"}; String randomColor = colors[(int)(Math.random() * colors.length)]; out.println("Random Color: " + randomColor); %> </body> </html> - Входные данные: Нет.
- Решение:
Сложные задачи:
Создайте приложение, которое позволяет пользователям регистрироваться и отображает список зарегистрированных пользователей.
- Решение: Используйте JSP, чтобы получить данные из формы и сохранить их в массиве или списке.
- Входные данные: Имя и возраст пользователя.
Создайте JSP-страницу, которая загружает и отображает изображения из указанной папки на сервере.
- Решение: Используйте
FileиServletContextдля получения файлов. - Входные данные: Путь к папке с изображениями.
- Решение: Используйте
Создайте простое приложение для чата, где сообщения пользователей отображаются на странице.
- Решение: Используйте сессии для хранения сообщений и отображения их на странице.
- Входные данные: Сообщение пользователя.
Создайте калькулятор, который принимает два числа и операцию, а затем показывает результат.
- Решение: Используйте
switchдля выполнения операций. - Входные данные: Числа и операция.
- Решение: Используйте
Создайте JSP-страницу, которая отображает данные о пользователе из базы данных MySQL.
- Решение: Используйте JDBC для подключения к базе данных и отображения данных.
- Входные данные: Данные о пользователе.
Создайте форму для загрузки файлов и отображения списка загруженных файлов.
- Решение: Используйте
Apache Commons FileUploadдля обработки загрузки файлов. - Входные данные: Файл для загрузки.
- Решение: Используйте
Создайте JSP-страницу, которая отображает график с использованием библиотек Chart.js.
- Решение: Используйте JavaScript для построения графика.
- Входные данные: Данные для графика.
Создайте приложение, которое сохраняет заметки пользователей и отображает их на странице.
- Решение: Используйте
ArrayListдля хранения заметок. - Входные данные: Заметка пользователя.
- Решение: Используйте
Создайте JSP-страницу, которая обрабатывает формы и отображает данные в таблице.
- Решение: Используйте HTML-таблицу для отображения данных.
- Входные данные: Данные из формы.
Создайте приложение, которое позволяет пользователям создавать и управлять событиями (добавление, удаление).
- Решение: Используйте массив или базу данных для хранения событий.
- Входные данные: Данные события.
2. РАБОТА С JSP В ECLIPSE
Базовые задачи:
Создайте новый проект JSP в Eclipse.
- Решение: Используйте меню "File" -> "New" -> "Dynamic Web Project".
- Входные данные: Нет.
Создайте новую JSP-страницу в проекте.
- Решение: Щелкните правой кнопкой мыши на проекте, выберите "New" -> "JSP File".
- Входные данные: Имя файла JSP.
Запустите JSP-страницу на сервере Apache Tomcat.
- Решение: Щелкните правой кнопкой мыши на проекте, выберите "Run As" -> "Run on Server".
- Входные данные: Нет.
Отредактируйте JSP-страницу и добавьте новый HTML-код.
- Решение: Используйте редактор JSP в Eclipse для редактирования кода.
- Входные данные: Новый HTML-код.
Используйте встроенные возможности Eclipse для отладки JSP-страниц.
- Решение: Установите точки останова и используйте "Debug" вместо "Run".
- Входные данные: Нет.
Создайте библиотеку тегов (tag library) в Eclipse и используйте её в JSP.
- Решение: Создайте новый проект Tag Library и добавьте пользовательский тег в JSP.
- Входные данные: Имя пользовательского тега.
Создайте и используйте шаблон JSP в Eclipse.
- Решение: Создайте файл .jsp и используйте его в других JSP-страницах.
- Входные данные: Нет.
Добавьте файл конфигурации web.xml в проект и настройте сервлеты.
- Решение: Используйте "web.xml" для маппинга сервлетов.
- Входные данные: Данные о сервлетах.
Создайте файл стилей CSS и подключите его к JSP-странице.
- Решение: Используйте тег
<link>для подключения CSS. - Входные данные: Путь к CSS-файлу.
- Решение: Используйте тег
Создайте новую страницу, используя стандартные JSP-директивы.
- Решение: Используйте
<%@ page %>для настройки страницы. - Входные данные: Директивы JSP.
- Решение: Используйте
Сложные задачи:
Создайте проект JSP с использованием шаблона MVC.
- Решение: Настройте контроллер, модель и представление.
- Входные данные: Нет.
Реализуйте функцию авторизации пользователя с использованием JSP и сервлетов.
- Решение: Настройте форму логина и обработчик на сервлете.
- Входные данные: Имя пользователя и пароль.
Настройте приложение JSP с использованием базы данных для хранения данных пользователей.
- Решение: Используйте JDBC для взаимодействия с базой данных.
- Входные данные: Данные о пользователе.
Реализуйте страницу администрирования, где администратор может редактировать пользователей.
- Решение: Создайте форму для редактирования и обработку данных.
- Входные данные: Данные о пользователе.
Создайте приложение с использованием AJAX для динамического обновления данных на странице.
- Решение: Используйте XMLHttpRequest для обновления данных.
- Входные данные: Данные для обновления.
Реализуйте функцию комментариев, где пользователи могут оставлять свои отзывы.
- Решение: Создайте форму для комментариев и храните их в базе данных.
- Входные данные: Комментарий пользователя.
Создайте приложение для блога, где пользователи могут создавать посты и комментировать их.
- Решение: Используйте JDBC для работы с постами и комментариями.
- Входные данные: Данные поста и комментария.
Реализуйте систему регистрации и входа с подтверждением электронной почты.
- Решение: Используйте JavaMail API для отправки писем.
- Входные данные: Адрес электронной почты.
Создайте приложение, которое отображает погоду на основе данных API.
- Решение: Используйте
HttpURLConnectionдля запроса данных. - Входные данные: Город для получения погоды.
- Решение: Используйте
Реализуйте систему рейтингов для пользователей, которые могут оценивать посты.
- Решение: Храните рейтинги в базе данных и отображайте их.
- Входные данные: Рейтинг поста.
3. ОСНОВЫ СИНТАКСИСА JSP
Базовые задачи:
Создайте JSP-страницу, которая использует выражения для отображения текста.
- Решение:jsp
<%-- expression.jsp --%> <html> <body> <h1>Welcome to JSP!</h1> <p>Current Year: <%= new java.util.Date().getYear() + 1900 %></p> </body> </html> - Входные данные: Нет.
- Решение:
Создайте JSP-страницу, которая использует скриптлеты для выполнения логики.
- Решение:jsp
<%-- scriptlet.jsp --%> <html> <body> <% int a = 5; int b = 10; out.println("Sum: " + (a + b)); %> </body> </html> - Входные данные: Нет.
- Решение:
Создайте JSP-страницу, которая использует директивы для импорта классов.
- Решение:jsp
<%@ page import="java.util.*" %> <html> <body> <% Date date = new Date(); out.println("Current Date: " + date); %> </body> </html> - Входные данные: Нет.
- Решение:
Создайте JSP-страницу, которая использует комментарии.
- Решение:jsp
<%-- comment.jsp --%> <html> <body> <h1>JSP Comments</h1> <%-- This is a JSP comment --%> <p>Comments are not displayed in the output.</p> </body> </html> - Входные данные: Нет.
- Решение:
Создайте JSP-страницу, которая использует условные конструкции.
- Решение:jsp
<%-- conditional.jsp --%> <html> <body> <% int number = 10; if (number % 2 == 0) { out.println("Number is even."); } else { out.println("Number is odd."); } %> </body> </html> - Входные данные: Нет.
- Решение:
Создайте JSP-страницу, которая использует цикл
for.- Решение:jsp
<%-- loop.jsp --%> <html> <body> <h1>Numbers from 1 to 5</h1> <ul> <% for (int i = 1; i <= 5; i++) { out.println("<li>" + i + "</li>"); } %> </ul> </body> </html> - Входные данные: Нет.
- Решение:
Создайте JSP-страницу, которая использует
Stringи методы.- Решение:jsp
<%-- stringMethods.jsp --%> <html> <body> <% String message = "Hello JSP"; out.println("Length of message: " + message.length()); %> </body> </html> - Входные данные: Нет.
- Решение:
Создайте JSP-страницу, которая показывает использование
Array.- Решение:jsp
<%-- array.jsp --%> <html> <body> <% String[] fruits = {"Apple", "Banana", "Cherry"}; out.println("Fruits: "); for (String fruit : fruits) { out.println(fruit + " "); } %> </body> </html> - Входные данные: Нет.
- Решение:
Создайте JSP-страницу, которая использует
Dateи форматирование.- Решение:jsp
<%-- dateFormat.jsp --%> <html> <body> <% java.text.SimpleDateFormat sdf = new java.text.SimpleDateFormat("dd-MM-yyyy"); out.println("Formatted Date: " + sdf.format(new java.util.Date())); %> </body> </html> - Входные данные: Нет.
- Решение:
Создайте JSP-страницу, которая обрабатывает параметры из строки запроса.
- Решение:jsp
<%-- paramHandling.jsp --%> <html> <body> <form action="paramHandling.jsp" method="get"> Enter your name: <input type="text" name="name"> <input type="submit" value="Submit"> </form> <% String name = request.getParameter("name"); if (name != null) { out.println("Hello, " + name + "!"); } %> </body> </html> - Входные данные: Параметр
name.
- Решение:
Создайте JSP-страницу, которая показывает информацию о сессии.
- Решение:jsp
<%-- sessionInfo.jsp --%> <html> <body> <% session.setAttribute("username", "John"); out.println("Session Username: " + session.getAttribute("username")); %> </body> </html> - Входные данные: Нет.
- Решение:
Создайте JSP-страницу, которая проверяет наличие параметра.
- Решение:jsp
<%-- paramCheck.jsp --%> <html> <body> <form action="paramCheck.jsp" method="get"> Check for parameter: <input type="text" name="paramName"> <input type="submit" value="Check"> </form> <% String paramName = request.getParameter("paramName"); if (paramName != null) { out.println("Parameter found: " + paramName); } else { out.println("Parameter not found."); } %> </body> </html> - Входные данные: Параметр
paramName.
- Решение:
Создайте JSP-страницу, которая отображает значения переменных окружения.
- Решение:jsp
<%-- envVariables.jsp --%> <html> <body> <h1>Environment Variables</h1> <% System.getenv().forEach((key, value) -> out.println(key + ": " + value + "<br>")); %> </body> </html> - Входные данные: Нет.
- Решение:
Создайте JSP-страницу, которая загружает и отображает JSON-данные.
- Решение:jsp
<%-- jsonDisplay.jsp --%> <html> <body> <h1>JSON Data</h1> <% String jsonData = "{\"name\":\"John\", \"age\":30}"; out.println("JSON: " + jsonData); %> </body> </html> - Входные данные: Нет.
- Решение:
Создайте JSP-страницу, которая обрабатывает POST-запрос.
- Решение:jsp
<%-- postHandling.jsp --%> <html> <body> <form action="postHandling.jsp" method="post"> Enter your email: <input type="email" name="email"> <input type="submit" value="Submit"> </form> <% String email = request.getParameter("email"); if (email != null) { out.println("Email submitted: " + email); } %> </body> </html> - Входные данные: Параметр
email.
- Решение:
Создайте JSP-страницу, которая обрабатывает ошибки.
- Решение:jsp
<%-- errorHandling.jsp --%> <html> <body> <% try { int result = 10 / 0; // This will cause an error } catch (Exception e) { out.println("Error: " + e.getMessage()); } %> </body> </html> - Входные данные: Нет.
- Решение:
Создайте JSP-страницу, которая показывает время сервера.
- Решение:jsp
<%-- serverTime.jsp --%> <html> <body> <% java.util.Date date = new java.util.Date(); out.println("Server Time: " + date); %> </body> </html> - Входные данные: Нет.
- Решение:
Создайте JSP-страницу, которая показывает текущую страницу.
- Решение:jsp
<%-- currentPage.jsp --%> <html> <body> <% String currentPage = request.getRequestURI(); out.println("Current Page: " + currentPage); %> </body> </html> - Входные данные: Нет.
- Решение:
Создайте JSP-страницу, которая обрабатывает загрузку файлов.
- Решение:jsp
<%-- fileUpload.jsp --%> <html> <body> <form action="fileUpload.jsp" method="post" enctype="multipart/form-data"> Select file: <input type="file" name="file"> <input type="submit" value="Upload"> </form> <% // Note: File upload requires additional handling. This is just a form. %> </body> </html> - Входные данные: Файл для загрузки.
- Решение:
Создайте JSP-страницу, которая генерирует случайное число.
- Решение:jsp
<%-- randomNumber.jsp --%> <html> <body> <% int randomNum = (int) (Math.random() * 100); out.println("Random Number: " + randomNum); %> </body> </html> - Входные данные: Нет.
- Решение:
Сложные задачи:
Создайте JSP-страницу с формой, которая передает данные на сервлет для обработки.
- Решение: Используйте
POSTдля передачи данных. - Входные данные: Данные формы.
- Решение: Используйте
Создайте JSP-страницу, которая показывает данные из базы данных MySQL.
- Решение: Используйте JDBC для подключения к базе данных и выборки данных.
- Входные данные: Данные базы данных.
Создайте JSP-страницу, которая обрабатывает файлы cookie.
- Решение: Используйте
javax.servlet.http.Cookie. - Входные данные: Данные для cookie.
- Решение: Используйте
Создайте JSP-страницу, которая генерирует QR-код на основе переданного текста.
- Решение: Используйте библиотеку для генерации QR-кодов.
- Входные данные: Текст для QR-кода.
Создайте JSP-страницу, которая отображает данные о пользователе, переданные через сессию.
- Решение: Храните данные пользователя в сессии и отображайте их.
- Входные данные: Данные о пользователе.
Создайте JSP-страницу, которая отправляет электронное письмо с использованием JavaMail API.
- Решение: Настройте JavaMail для отправки сообщений.
- Входные данные: Данные для отправки почты.
Создайте JSP-страницу, которая отображает данные о погоде с использованием внешнего API.
- Решение: Используйте
HttpURLConnectionдля получения данных. - Входные данные: Город для получения погоды.
- Решение: Используйте
Создайте JSP-страницу с формой, которая принимает параметры и отображает результаты в виде графика.
- Решение: Используйте JavaScript для построения графика.
- Входные данные: Данные для графика.
Создайте JSP-страницу, которая использует AJAX для отправки и получения данных без перезагрузки страницы.
- Решение: Используйте
XMLHttpRequest. - Входные данные: Данные для отправки.
- Решение: Используйте
Создайте JSP-страницу, которая реализует аутентификацию пользователей с использованием базовых методов.
- Решение: Используйте формы для входа и проверки.
- Входные данные: Имя пользователя и пароль.
2. СОЗДАНИЕ ПРОСТОГО ПРИЛОЖЕНИЯ
Базовые задачи:
Создайте простое Spring-приложение с использованием XML-конфигурации.
- Решение:java
// AppConfig.xml <beans xmlns="http://www.springframework.org/schema/beans"> <bean id="helloService" class="com.example.HelloService" /> </beans>java// HelloService.java public class HelloService { public void sayHello() { System.out.println("Hello, Spring!"); } }- Входные данные: Нет.
- Решение:
Создайте Spring-приложение с использованием Java-конфигурации.
- Решение:java
@Configuration public class AppConfig { @Bean public HelloService helloService() { return new HelloService(); } }javapublic class HelloService { public void sayHello() { System.out.println("Hello, Spring!"); } }- Входные данные: Нет.
- Решение:
Настройте Spring-приложение для автоматического сканирования компонентов.
- Решение:java
@ComponentScan("com.example") @Configuration public class AppConfig { }java@Component public class HelloService { public void sayHello() { System.out.println("Hello, Spring!"); } }- Входные данные: Нет.
- Решение:
Создайте и настройте Spring-приложение с использованием аннотации
@Configuration.- Решение:java
@Configuration public class AppConfig { @Bean public HelloService helloService() { return new HelloService(); } }- Входные данные: Нет.
- Решение:
Создайте Spring-приложение с аннотацией
@Bean.- Решение:java
@Configuration public class AppConfig { @Bean public HelloService helloService() { return new HelloService(); } }- Входные данные: Нет.
- Решение:
Настройте Spring-приложение с использованием аннотации
@Component.- Решение:java
@Component public class HelloService { public void sayHello() { System.out.println("Hello, Spring!"); } }- Входные данные: Нет.
- Решение:
Создайте Spring-приложение с использованием Java-based конфигурации.
- Решение:java
@Configuration public class AppConfig { @Bean public HelloService helloService() { return new HelloService(); } }- Входные данные: Нет.
- Решение:
Реализуйте запуск Spring-приложения с помощью
ApplicationContext.- Решение:java
public class MainApp { public static void main(String[] args) { ApplicationContext context = new AnnotationConfigApplicationContext(AppConfig.class); HelloService helloService = context.getBean(HelloService.class); helloService.sayHello(); } }- Входные данные: Нет.
- Решение:
Настройте и реализуйте простое приложение Spring с использованием файла
applicationContext.xml.- Решение:xml
<beans xmlns="http://www.springframework.org/schema/beans"> <bean id="helloService" class="com.example.HelloService"/> </beans>javapublic class MainApp { public static void main(String[] args) { ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml"); HelloService helloService = (HelloService) context.getBean("helloService"); helloService.sayHello(); } }- Входные данные: Нет.
- Решение:
Создайте Spring-приложение с использованием аннотации
@Autowired.- Решение:java
@Component public class HelloService { public void sayHello() { System.out.println("Hello, Spring!"); } }java@Component public class MainApp { @Autowired private HelloService helloService; public static void main(String[] args) { ApplicationContext context = new AnnotationConfigApplicationContext(AppConfig.class); MainApp app = context.getBean(MainApp.class); app.helloService.sayHello(); } }- Входные данные: Нет.
- Решение:
Создайте Spring-приложение с использованием аннотации
@ComponentScan.- Решение:java
@ComponentScan("com.example") @Configuration public class AppConfig { }java@Component public class HelloService { public void sayHello() { System.out.println("Hello, Spring!"); } }- Входные данные: Нет.
- Решение:
Реализуйте Spring-приложение с использованием интерфейсов и внедрением зависимостей.
- Решение:java
public interface GreetingService { void greet(); } @Component public class HelloService implements GreetingService { @Override public void greet() { System.out.println("Hello, Spring!"); } }java@Component public class MainApp { @Autowired private GreetingService greetingService; public static void main(String[] args) { ApplicationContext context = new AnnotationConfigApplicationContext(AppConfig.class); MainApp app = context.getBean(MainApp.class); app.greetingService.greet(); } }- Входные данные: Нет.
- Решение:
Создайте Spring-приложение с использованием нескольких конфигурационных классов.
- Решение:java
@Configuration public class AppConfig { @Bean public HelloService helloService() { return new HelloService(); } }java@Configuration @Import(AppConfig.class) public class MainConfig { }- Входные данные: Нет.
- Решение:
Реализуйте приложение с несколькими контекстами в Spring.
- Решение:java
ApplicationContext parent = new AnnotationConfigApplicationContext(ParentConfig.class); ApplicationContext child = new AnnotationConfigApplicationContext(ChildConfig.class);- Входные данные: Нет.
- Решение:
Настройте Spring-приложение с использованием
@Qualifierдля выбора конкретного бина.- Решение:java
@Component public class HelloService implements GreetingService { @Override public void greet() { System.out.println("Hello, Spring!"); } }java@Component public class MainApp { @Autowired @Qualifier("helloService") private GreetingService greetingService; }- Входные данные: Нет.
- Решение:
Настройте Spring-приложение для внедрения списка зависимостей.
- Решение:java
@Configuration public class AppConfig { @Bean public List<GreetingService> greetingServices() { return List.of(new HelloService(), new GoodbyeService()); } }- Входные данные: Нет.
- Решение:
Создайте Spring-приложение с внедрением
Map.- Решение:java
@Configuration public class AppConfig { @Bean public Map<String, GreetingService> greetingMap() { Map<String, GreetingService> map = new HashMap<>(); map.put("hello", new HelloService()); return map; } }- Входные данные: Нет.
- Решение:
Настройте приложение с поддержкой
@Primary.- Решение:java
@Component @Primary public class HelloService implements GreetingService { }- Входные данные: Нет.
- Решение:
Реализуйте приложение с прототипом бина.
- Решение:java
@Scope("prototype") @Component public class HelloService { }- Входные данные: Нет.
- Решение:
Настройте приложение с конфигурированием по аннотации
@Lazy.- Решение:java
@Lazy @Component public class HelloService { }- Входные данные: Нет.
- Решение:
Сложные задачи:
Реализуйте приложение с использованием Spring Boot и базовой структурой REST.
- Решение:java
@RestController public class GreetingController { @GetMapping("/greet") public String greet() { return "Hello, Spring Boot!"; } }- Входные данные: Запрос GET.
- Решение:
Создайте Spring-приложение с использованием ORM Hibernate.
- Решение: Включите зависимость Spring ORM и настройте Hibernate.
- Входные данные: Объекты базы данных.
Настройте Spring-приложение с асинхронным выполнением методов.
- Решение:java
@Async public void asyncMethod() { // some background task }- Входные данные: Нет.
- Решение:
Создайте приложение с использование механизмов транзакций Spring.
- Решение: Настройте аннотацию
@Transactional. - Входные данные: Транзакционные данные.
- Решение: Настройте аннотацию
Настройте приложение для работы с кэшированием с помощью аннотации
@Cacheable.- Решение:java
@Cacheable("greetings") public String getGreeting(String name) { return "Hello " + name; }- Входные данные: Параметры для кэширования.
- Решение:
Реализуйте Spring-приложение с созданием настраиваемых аннотаций.
- Решение: Создайте свою аннотацию и свяжите с логикой в
AOP. - Входные данные: Аннотация.
- Решение: Создайте свою аннотацию и свяжите с логикой в
Внедрите в приложение использование RabbitMQ для очередей сообщений.
- Решение: Настройте Spring RabbitMQ и свяжите с брокером сообщений.
- Входные данные: Сообщения для отправки.
Настройте приложение для работы с
WebSocket.- Решение: Включите поддержку
WebSocketи создайте эндпоинты. - Входные данные: Данные WebSocket.
- Решение: Включите поддержку
Реализуйте приложение с использованием фильтров в Spring Security.
- Решение: Настройте фильтры безопасности для работы с запросами.
- Входные данные: Безопасные данные.
Создайте приложение с внедрением динамической обработки событий Spring.
- Решение: Используйте
ApplicationEventPublisherдля кастомных событий. - Входные данные: Данные события.
- Решение: Используйте
СЕТЬЮ
Базовые задачи
Создание сокет-соединения между клиентом и сервером.
- Решение:java
// Сервер ServerSocket serverSocket = new ServerSocket(8080); Socket clientSocket = serverSocket.accept(); PrintWriter out = new PrintWriter(clientSocket.getOutputStream(), true); out.println("Hello, client!");java// Клиент Socket socket = new Socket("localhost", 8080); BufferedReader in = new BufferedReader(new InputStreamReader(socket.getInputStream())); System.out.println(in.readLine()); - Входные данные: Соединение между сервером и клиентом.
- Решение:
Отправка сообщения от клиента к серверу через сокет.
- Решение:java
// Клиент Socket socket = new Socket("localhost", 8080); PrintWriter out = new PrintWriter(socket.getOutputStream(), true); out.println("Hello, server!"); - Входные данные: Сообщение от клиента.
- Решение:
Создание многопоточного сервера для обслуживания нескольких клиентов.
- Решение:java
// Сервер while (true) { Socket clientSocket = serverSocket.accept(); new Thread(() -> handleClient(clientSocket)).start(); } - Входные данные: Несколько клиентских соединений.
- Решение:
Создание UDP-сокет-соединения.
- Решение:java
DatagramSocket socket = new DatagramSocket(); byte[] buffer = "Hello".getBytes(); DatagramPacket packet = new DatagramPacket(buffer, buffer.length, InetAddress.getByName("localhost"), 8080); socket.send(packet); - Входные данные: Данные для отправки через UDP.
- Решение:
Чтение данных с веб-страницы с помощью класса
URL.- Решение:java
URL url = new URL("http://example.com"); BufferedReader in = new BufferedReader(new InputStreamReader(url.openStream())); String inputLine; while ((inputLine = in.readLine()) != null) { System.out.println(inputLine); } - Входные данные: URL-адрес для получения данных.
- Решение:
Создание простого HTTP-сервера на основе Java Sockets.
- Решение:java
ServerSocket serverSocket = new ServerSocket(8080); while (true) { Socket clientSocket = serverSocket.accept(); PrintWriter out = new PrintWriter(clientSocket.getOutputStream(), true); out.println("HTTP/1.1 200 OK\nContent-Type: text/html\n\nHello, world!"); } - Входные данные: HTTP-запросы от клиента.
- Решение:
Чтение IP-адреса удаленного сервера.
- Решение:java
InetAddress address = InetAddress.getByName("www.google.com"); System.out.println("IP Address: " + address.getHostAddress()); - Входные данные: Доменное имя.
- Решение:
Использование класса
MulticastSocketдля групповой отправки сообщений.- Решение:java
MulticastSocket socket = new MulticastSocket(); InetAddress group = InetAddress.getByName("224.0.0.1"); socket.joinGroup(group); byte[] buffer = "Hello multicast".getBytes(); DatagramPacket packet = new DatagramPacket(buffer, buffer.length, group, 4446); socket.send(packet); - Входные данные: Сообщение для отправки в группу.
- Решение:
Получение и отправка данных с использованием протокола TCP.
- Решение:java
Socket socket = new Socket("localhost", 8080); PrintWriter out = new PrintWriter(socket.getOutputStream(), true); out.println("Hello, TCP!"); - Входные данные: TCP-соединение.
- Решение:
Реализация сервера для передачи файлов между клиентом и сервером.
- Решение:java
FileInputStream fis = new FileInputStream("file.txt"); OutputStream os = clientSocket.getOutputStream(); byte[] buffer = new byte[1024]; int bytesRead; while ((bytesRead = fis.read(buffer)) != -1) { os.write(buffer, 0, bytesRead); } - Входные данные: Файл для передачи.
- Решение:
...
Сложные задачи
Реализация сервера чата с поддержкой нескольких клиентов.
- Решение:java
public class ChatServer { private List<ClientHandler> clients = new ArrayList<>(); public void broadcast(String message) { for (ClientHandler client : clients) { client.sendMessage(message); } } } - Входные данные: Сообщения от клиентов.
- Решение:
Создание P2P-приложения для обмена файлами через сокеты.
- Решение: Используйте сокеты и многопоточность для передачи файлов между клиентами.
Разработка HTTP-сервера с поддержкой загрузки файлов.
- Решение: Реализуйте обработку HTTP-запросов для загрузки файлов через POST-запрос.
FORK/JOIN FRAMEWORK: МОДЕЛЬ ДЛЯ РАСПАРАЛЛЕЛИВАНИЯ ЗАДАЧ
Базовые задачи
Задача: Написать программу для суммирования чисел в массиве с помощью Fork/Join Framework.
- Входные данные: массив чисел.
- Пример кода:java
import java.util.concurrent.RecursiveTask; import java.util.concurrent.ForkJoinPool; class SumTask extends RecursiveTask<Integer> { private final int[] array; private final int start, end; public SumTask(int[] array, int start, int end) { this.array = array; this.start = start; this.end = end; } @Override protected Integer compute() { if (end - start <= 10) { int sum = 0; for (int i = start; i < end; i++) { sum += array[i]; } return sum; } else { int middle = (start + end) / 2; SumTask leftTask = new SumTask(array, start, middle); SumTask rightTask = new SumTask(array, middle, end); leftTask.fork(); int rightResult = rightTask.compute(); int leftResult = leftTask.join(); return leftResult + rightResult; } } } public class ForkJoinSum { public static void main(String[] args) { int[] array = new int[100]; for (int i = 0; i < array.length; i++) { array[i] = i; } ForkJoinPool pool = new ForkJoinPool(); SumTask task = new SumTask(array, 0, array.length); int result = pool.invoke(task); System.out.println("Sum: " + result); } }
Задача: Реализовать параллельную сортировку массива.
- Входные данные: массив чисел.
- Пример кода:java
import java.util.concurrent.RecursiveAction; import java.util.concurrent.ForkJoinPool; class SortTask extends RecursiveAction { private final int[] array; private final int start, end; public SortTask(int[] array, int start, int end) { this.array = array; this.start = start; this.end = end; } @Override protected void compute() { if (end - start <= 10) { bubbleSort(array, start, end); } else { int middle = (start + end) / 2; SortTask leftTask = new SortTask(array, start, middle); SortTask rightTask = new SortTask(array, middle, end); invokeAll(leftTask, rightTask); merge(array, start, middle, end); } } private void bubbleSort(int[] array, int start, int end) { for (int i = start; i < end; i++) { for (int j = i + 1; j < end; j++) { if (array[i] > array[j]) { int temp = array[i]; array[i] = array[j]; array[j] = temp; } } } } private void merge(int[] array, int start, int middle, int end) { int[] temp = new int[end - start]; int i = start, j = middle, k = 0; while (i < middle && j < end) { if (array[i] < array[j]) { temp[k++] = array[i++]; } else { temp[k++] = array[j++]; } } while (i < middle) { temp[k++] = array[i++]; } while (j < end) { temp[k++] = array[j++]; } System.arraycopy(temp, 0, array, start, temp.length); } } public class ForkJoinSort { public static void main(String[] args) { int[] array = {7, 2, 9, 1, 5, 3, 6, 4, 8}; ForkJoinPool pool = new ForkJoinPool(); SortTask task = new SortTask(array, 0, array.length); pool.invoke(task); for (int i : array) { System.out.print(i + " "); } } }
Задача: Написать программу для параллельного подсчета факториалов чисел.
- Входные данные: число
n. - Пример кода:java
import java.util.concurrent.RecursiveTask; import java.util.concurrent.ForkJoinPool; class FactorialTask extends RecursiveTask<Long> { private final int number; public FactorialTask(int number) { this.number = number; } @Override protected Long compute() { if (number <= 1) { return 1L; } FactorialTask subTask = new FactorialTask(number - 1); subTask.fork(); return number * subTask.join(); } } public class ForkJoinFactorial { public static void main(String[] args) { ForkJoinPool pool = new ForkJoinPool(); FactorialTask task = new FactorialTask(10); long result = pool.invoke(task); System.out.println("Factorial: " + result); } }
- Входные данные: число
Задача: Использовать Fork/Join Framework для подсчета количества четных чисел в массиве.
- Входные данные: массив чисел.
- Пример кода:java
import java.util.concurrent.RecursiveTask; import java.util.concurrent.ForkJoinPool; class EvenCountTask extends RecursiveTask<Integer> { private final int[] array; private final int start, end; public EvenCountTask(int[] array, int start, int end) { this.array = array; this.start = start; this.end = end; } @Override protected Integer compute() { if (end - start <= 10) { int count = 0; for (int i = start; i < end; i++) { if (array[i] % 2 == 0) { count++; } } return count; } else { int middle = (start + end) / 2; EvenCountTask leftTask = new EvenCountTask(array, start, middle); EvenCountTask rightTask = new EvenCountTask(array, middle, end); leftTask.fork(); int rightResult = rightTask.compute(); int leftResult = leftTask.join(); return leftResult + rightResult; } } } public class ForkJoinEvenCount { public static void main(String[] args) { int[] array = new int[100]; for (int i = 0; i < array.length; i++) { array[i] = i; } ForkJoinPool pool = new ForkJoinPool(); EvenCountTask task = new EvenCountTask(array, 0, array.length); int result = pool.invoke(task); System.out.println("Even numbers count: " + result); } }
Задача: Программа для параллельного вычисления максимального значения в массиве.
- Входные данные: массив чисел.
- Пример кода:java
import java.util.concurrent.RecursiveTask; import java.util.concurrent.ForkJoinPool; class MaxTask extends RecursiveTask<Integer> { private final int[] array; private final int start, end; public MaxTask(int[] array, int start, int end) { this.array = array; this.start = start; this.end = end; } @Override protected Integer compute() { if (end - start <= 10) { int max = array[start]; for (int i = start + 1; i < end; i++) { if (array[i] > max) { max = array[i]; } } return max; } else { int middle = (start + end) / 2; MaxTask leftTask = new MaxTask(array, start, middle); MaxTask rightTask = new MaxTask(array, middle, end); leftTask.fork(); int rightResult = rightTask.compute(); int leftResult = leftTask.join(); return Math.max(leftResult, rightResult); } } } public class ForkJoinMax { public static void main(String[] args) { int[] array = {7, 2, 9, 1, 5, 3, 6, 4, 8}; ForkJoinPool pool = new ForkJoinPool(); MaxTask task = new MaxTask(array, 0, array.length); int result = pool.invoke(task); System.out.println("Max value: " + result); } }
Задача: Параллельный поиск минимального значения в массиве.
- Входные данные: массив чисел.
Задача: Использовать Fork/Join Framework для параллельного вычисления среднего значения массива.
- Входные данные: массив чисел.
Задача: Написать программу для вычисления количества простых чисел в диапазоне от 1 до
n.- Входные данные: число
n.
- Входные данные: число
Задача: Параллельное умножение элементов массива на заданное число.
- Входные данные: массив чисел и множитель.
Задача: Реализовать параллельное умножение двух матриц.
- Входные данные: две матрицы.
Сложные задачи
- Задача: Написать программу для параллельного перемножения больших матриц с оптимизацией производительности.
- Задача: Использовать Fork/Join Framework для реализации алгоритма быстрой сортировки.
- Задача: Параллельная обработка большого файла, разбитого на части, с последующей агрегацией результатов.
- Задача: Написать программу для параллельного поиска самого длинного слова в большом тексте.
- Задача: Оптимизировать алгоритм вычисления чисел Фибоначчи с помощью Fork/Join Framework.
- Задача: Реализовать параллельный алгоритм нахождения кратчайшего пути в графе.
- Задача: Написать программу для распараллеливания алгоритма сортировки слиянием.
- Задача: Применение Fork/Join Framework для выполнения больших наборов тестов с разбиением на задачи.
- Задача: Использовать Fork/Join Framework для обработки большого количества API-запросов с агрегацией результатов.
- Задача: Параллельная обработка видеопотока с использованием Fork/Join Framework.
РАЗДЕЛ 1: HIBERNATE И JPA (ORM-ТЕХНОЛОГИИ ДЛЯ РАБОТЫ С БАЗАМИ ДАННЫХ)
Базовые задачи
Задача: Настройка простого Hibernate-приложения.
- Входные данные: База данных H2 или MySQL.
- Пример кода:java
@Entity public class User { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) private Long id; private String name; private String email; // Getters and setters } public class HibernateUtil { private static SessionFactory sessionFactory; static { sessionFactory = new Configuration().configure().buildSessionFactory(); } public static SessionFactory getSessionFactory() { return sessionFactory; } } public class Main { public static void main(String[] args) { Session session = HibernateUtil.getSessionFactory().openSession(); session.beginTransaction(); User user = new User(); user.setName("John"); user.setEmail("john@example.com"); session.save(user); session.getTransaction().commit(); session.close(); } }
Задача: Создать и сохранить в базу данных простой объект класса
Product.- Входные данные: таблица
productsв базе данных. - Пример кода:java
@Entity public class Product { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) private Long id; private String name; private double price; // Getters and setters } public class Main { public static void main(String[] args) { Session session = HibernateUtil.getSessionFactory().openSession(); session.beginTransaction(); Product product = new Product(); product.setName("Laptop"); product.setPrice(800.0); session.save(product); session.getTransaction().commit(); session.close(); } }
- Входные данные: таблица
Задача: Найти объект по его ID в базе данных с использованием Hibernate.
- Входные данные: ID объекта
Userв базе данных. - Пример кода:java
public class Main { public static void main(String[] args) { Session session = HibernateUtil.getSessionFactory().openSession(); User user = session.get(User.class, 1L); System.out.println(user.getName()); session.close(); } }
- Входные данные: ID объекта
Задача: Обновить объект в базе данных с помощью Hibernate.
- Входные данные: существующий объект
Userс новым email. - Пример кода:java
public class Main { public static void main(String[] args) { Session session = HibernateUtil.getSessionFactory().openSession(); session.beginTransaction(); User user = session.get(User.class, 1L); user.setEmail("newemail@example.com"); session.update(user); session.getTransaction().commit(); session.close(); } }
- Входные данные: существующий объект
Задача: Удалить объект из базы данных с помощью Hibernate.
- Входные данные: ID объекта
Productдля удаления. - Пример кода:java
public class Main { public static void main(String[] args) { Session session = HibernateUtil.getSessionFactory().openSession(); session.beginTransaction(); Product product = session.get(Product.class, 1L); session.delete(product); session.getTransaction().commit(); session.close(); } }
- Входные данные: ID объекта
Задача: Написать запрос HQL для получения всех пользователей.
- Входные данные: таблица
users. - Пример кода:java
public class Main { public static void main(String[] args) { Session session = HibernateUtil.getSessionFactory().openSession(); List<User> users = session.createQuery("from User", User.class).list(); for (User user : users) { System.out.println(user.getName()); } session.close(); } }
- Входные данные: таблица
Задача: Использовать аннотацию @Column для задания нестандартного имени колонки.
- Входные данные: объект с колонкой
email_address. - Пример кода:java
@Entity public class User { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) private Long id; @Column(name = "email_address") private String email; // Getters and setters }
- Входные данные: объект с колонкой
Задача: Настроить связь One-to-Many между
UserиOrder.- Входные данные: таблицы
usersиorders. - Пример кода:java
@Entity public class User { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) private Long id; private String name; @OneToMany(mappedBy = "user") private List<Order> orders; // Getters and setters } @Entity public class Order { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) private Long id; private String product; @ManyToOne @JoinColumn(name = "user_id") private User user; // Getters and setters }
- Входные данные: таблицы
Задача: Использовать @ManyToMany связь между сущностями
StudentиCourse.- Входные данные: таблицы
studentsиcourses. - Пример кода:java
@Entity public class Student { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) private Long id; private String name; @ManyToMany @JoinTable( name = "student_course", joinColumns = @JoinColumn(name = "student_id"), inverseJoinColumns = @JoinColumn(name = "course_id") ) private List<Course> courses; // Getters and setters } @Entity public class Course { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) private Long id; private String name; @ManyToMany(mappedBy = "courses") private List<Student> students; // Getters and setters }
- Входные данные: таблицы
Задача: Пример использования @Temporal для работы с датами.
- Входные данные: объект с датой.
- Пример кода:java
@Entity public class User { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) private Long id; @Temporal(TemporalType.DATE) private Date birthDate; // Getters and setters }
- Задача: Использовать @Embedded для встраивания объекта Address в сущность User.
- Входные данные: объект
Address. - Пример кода:java
@Embeddable public class Address { private String street; private String city; // Getters and setters } @Entity public class User { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) private Long id; @Embedded private Address address; // Getters and setters }
- Задача: Пример использования @Query для выполнения кастомного запроса в JPA.
- Входные данные: email пользователя.
- Пример кода:java
@Repository public interface UserRepository extends JpaRepository<User, Long> { @Query("SELECT u FROM User u WHERE u.email = ?1") User findByEmail(String email); }
- Задача: Создать связь One-to-One между сущностями
UserиProfile.
- Входные данные: таблицы
usersиprofiles. - Пример кода:java
@Entity public class User { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) private Long id; private String name; @OneToOne @JoinColumn(name = "profile_id") private Profile profile; // Getters and setters } @Entity public class Profile { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) private Long id; private String bio; // Getters and setters }
- Задача: Использовать @Inheritance для настройки наследования классов в JPA.
- Входные данные: таблицы
employeeиmanager. - Пример кода:java
@Entity @Inheritance(strategy = InheritanceType.SINGLE_TABLE) @DiscriminatorColumn(name = "role", discriminatorType = DiscriminatorType.STRING) public class Employee { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) private Long id; private String name; // Getters and setters } @Entity @DiscriminatorValue("Manager") public class Manager extends Employee { private String department; // Getters and setters }
- Задача: Настроить кэширование объектов в Hibernate для повышения производительности.
- Входные данные: кэширование для сущности
Product. - Пример кода:java
@Entity @Cacheable @Cache(usage = CacheConcurrencyStrategy.READ_WRITE) public class Product { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) private Long id; private String name; private double price; // Getters and setters }
- Задача: Использовать аннотацию @JoinColumn для указания внешнего ключа в связи Many-to-One.
- Входные данные: таблицы
ordersиusers. - Пример кода:java
@Entity public class Order { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) private Long id; private String product; @ManyToOne @JoinColumn(name = "user_id") private User user; // Getters and setters }
- Задача: Пример использования @OneToMany с каскадными операциями (cascade).
- Входные данные: таблицы
usersиorders. - Пример кода:java
@Entity public class User { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) private Long id; private String name; @OneToMany(mappedBy = "user", cascade = CascadeType.ALL) private List<Order> orders; // Getters and setters }
- Задача: Реализовать ленивую инициализацию коллекции с использованием FetchType.LAZY.
- Входные данные: таблицы
usersиorders. - Пример кода:java
@Entity public class User { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) private Long id; private String name; @OneToMany(mappedBy = "user", fetch = FetchType.LAZY) private List<Order> orders; // Getters and setters }
- Задача: Использовать JPA для выполнения поиска с фильтрацией по нескольким параметрам.
- Входные данные: фильтрация по имени и email.
- Пример кода:java
@Repository public interface UserRepository extends JpaRepository<User, Long> { List<User> findByNameAndEmail(String name, String email); }
- Задача: Использовать @ElementCollection для хранения коллекции простых типов.
- Входные данные: список телефонных номеров.
- Пример кода:java
@Entity public class User { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) private Long id; private String name; @ElementCollection private List<String> phoneNumbers; // Getters and setters }
Сложные задачи
Задача: Реализовать многоуровневое кэширование в Hibernate.
- Входные данные: база данных с таблицами
productsиcategories. - Пример кода:java
@Entity @Cacheable @Cache(usage = CacheConcurrencyStrategy.READ_WRITE) public class Product { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) private Long id; private String name; private double price; @ManyToOne @JoinColumn(name = "category_id") private Category category; // Getters and setters }
- Входные данные: база данных с таблицами
Задача: Реализовать стратегию разделения таблиц (table partitioning) с помощью JPA.
- Входные данные: таблица
ordersс разбиением по годам.
- Входные данные: таблица
Задача: Настроить связь Many-to-Many с дополнительными атрибутами в промежуточной таблице.
- Входные данные: таблицы
studentsиcoursesс промежуточной таблицейstudent_courses.
- Входные данные: таблицы
Задача: Реализовать сложный запрос с несколькими соединениями таблиц через JPA.
- Входные данные: таблицы
users,orders,products.
- Входные данные: таблицы
Задача: Создать сущности с помощью генерации UUID в качестве ключа.
- Входные данные: таблица с UUID в качестве первичного ключа.
Задача: Реализовать поддержку различных баз данных с использованием JPA и Hibernate (MySQL, PostgreSQL).
- Входные данные: конфигурация нескольких баз данных.
Задача: Использовать @SecondaryTable для разбиения сущности по нескольким таблицам.
- Входные данные: таблицы
user_infoиuser_address.
- Входные данные: таблицы
Задача: Использовать JPA для создания иерархической структуры с помощью дерева (Tree structure).
- Входные данные: таблица
categoriesс деревом категорий.
- Входные данные: таблица
Задача: Применить стратегию Optimistic Locking для конкурентного обновления данных.
- Входные данные: база данных с таблицей
products.
- Входные данные: база данных с таблицей
Задача: Реализовать распределенную обработку транзакций с использованием JPA и Spring.
РАЗДЕЛ 2: SPRING DATA JPA
Базовые задачи
Задача: Создать простой Spring Boot проект с использованием Spring Data JPA.
- Входные данные: база данных MySQL.
- Пример кода:java
@Entity public class User { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) private Long id; private String name; private String email; // Getters and setters } @Repository public interface UserRepository extends JpaRepository<User, Long> { } @SpringBootApplication public class Application { public static void main(String[] args) { SpringApplication.run(Application.class, args); } }
Задача: Написать метод для поиска объекта по имени с помощью Spring Data JPA.
- Входные данные: имя пользователя.
- Пример кода:java
@Repository public interface UserRepository extends JpaRepository<User, Long> { User findByName(String name); }
Задача: Реализовать пагинацию и сортировку с использованием Spring Data JPA.
- Входные данные: список пользователей.
- Пример кода:java
@Repository public interface UserRepository extends JpaRepository<User, Long> { Page<User> findAll(Pageable pageable); } public class UserService { @Autowired private UserRepository userRepository; public Page<User> getUsers(int page, int size) { Pageable pageable = PageRequest.of(page, size, Sort.by("name").ascending()); return userRepository.findAll(pageable); } }
Задача: Создать запрос с использованием @Query для кастомного запроса.
- Входные данные: список пользователей по email.
- Пример кода:java
@Repository public interface UserRepository extends JpaRepository<User, Long> { @Query("SELECT u FROM User u WHERE u.email = ?1") User findByEmail(String email); }
Задача: Использовать @Modifying и @Query для обновления данных в базе.
- Входные данные: обновление email пользователя по его ID.
- Пример кода:java
@Repository public interface UserRepository extends JpaRepository<User, Long> { @Modifying @Query("UPDATE User u SET u.email = ?1 WHERE u.id = ?2") void updateEmailById(String email, Long id); }
Задача: Реализовать удаление пользователя по его ID с использованием Spring Data JPA.
- Входные данные: ID пользователя.
- Пример кода:java
@Repository public interface UserRepository extends JpaRepository<User, Long> { void deleteById(Long id); }
Задача: Использовать @Transactional для выполнения нескольких операций с базой.
- Входные данные: создание и удаление объектов.
- Пример кода:java
@Service public class UserService { @Autowired private UserRepository userRepository; @Transactional public void createUserAndDelete(Long userId) { User user = new User(); user.setName("John"); user.setEmail("john@example.com"); userRepository.save(user); userRepository.deleteById(userId); } }
Задача: Настроить кэширование для метода поиска пользователя по имени.
- Входные данные: имя пользователя.
- Пример кода:java
@Service public class UserService { @Autowired private UserRepository userRepository; @Cacheable("users") public User findByName(String name) { return userRepository.findByName(name); } }
Задача: Использовать спецификации для построения динамических запросов.
- Входные данные: фильтрация пользователей по нескольким параметрам.
- Пример кода:java
public class UserSpecification { public static Specification<User> hasName(String name) { return (root, query, criteriaBuilder) -> criteriaBuilder.equal(root.get("name"), name); } public static Specification<User> hasEmail(String email) { return (root, query, criteriaBuilder) -> criteriaBuilder.equal(root.get("email"), email); } } @Repository public interface UserRepository extends JpaRepository<User, Long>, JpaSpecificationExecutor<User> { } public class UserService { @Autowired private UserRepository userRepository; public List<User> findUsers(String name, String email) { return userRepository.findAll(Specification.where(UserSpecification.hasName(name)) .and(UserSpecification.hasEmail(email))); } }
Задача: Использовать @PrePersist и @PostPersist для обработки данных до и после сохранения.
- Входные данные: логирование сохранения пользователя.
- Пример кода:java
@Entity public class User { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) private Long id; private String name; @PrePersist public void beforeSave() { System.out.println("Saving user: " + name); } @PostPersist public void afterSave() { System.out.println("User saved: " + name); } // Getters and setters }
Сложные задачи
Задача: Использовать Spring Data JPA для построения сложных динамических запросов с фильтрацией, сортировкой и пагинацией.
Задача: Реализовать механизм batch-вставки данных в базу данных с использованием Spring Data JPA.
Задача: Настроить многопоточное выполнение транзакций с использованием Spring Data JPA.
Задача: Использовать @EntityGraph для оптимизации запросов с выбором связанных сущностей.
Задача: Реализовать поддержку нескольких баз данных в одном проекте с использованием Spring Data JPA.
Задача: Настроить сложную схему наследования в JPA с использованием стратегии TABLE_PER_CLASS.
Задача: Оптимизировать производительность запросов в Spring Data JPA с использованием @QueryHints и кэширования.
Задача: Использовать Spring Data JPA для работы с большими объемами данных и их разбивкой на партии (batch processing).
Задача: Реализовать распределенные транзакции с использованием JPA и Spring Data.
Задача: Настроить аудит данных с использованием Spring Data JPA и Hibernate Envers для отслеживания изменений.
РАЗДЕЛ 3: SQL ЧЕРЕЗ JDBC (ОПТИМИЗАЦИЯ ЗАПРОСОВ, ИСПОЛЬЗОВАНИЕ SQL-ПАКЕТОВ)
Базовые задачи
Задача: Создать подключение к базе данных с использованием JDBC.
- Входные данные: база данных MySQL.
- Пример кода:java
public class Main { public static void main(String[] args) { try (Connection connection = DriverManager.getConnection("jdbc:mysql://localhost:3306/mydb", "user", "password")) { System.out.println("Connection successful!"); } catch (SQLException e) { e.printStackTrace(); } } }
Задача: Выполнить SQL-запрос на выборку данных из таблицы с помощью JDBC.
- Входные данные: таблица
users. - Пример кода:java
public class Main { public static void main(String[] args) { try (Connection connection = DriverManager.getConnection("jdbc:mysql://localhost:3306/mydb", "user", "password"); Statement statement = connection.createStatement(); ResultSet resultSet = statement.executeQuery("SELECT * FROM users")) { while (resultSet.next()) { System.out.println(resultSet.getString("name")); } } catch (SQLException e) { e.printStackTrace(); } } }
- Входные данные: таблица
Задача: Использовать PreparedStatement для выполнения параметризованных запросов.
- Входные данные: имя пользователя для поиска.
- Пример кода:java
public class Main { public static void main(String[] args) { String name = "John"; try (Connection connection = DriverManager.getConnection("jdbc:mysql://localhost:3306/mydb", "user", "password"); PreparedStatement preparedStatement = connection.prepareStatement("SELECT * FROM users WHERE name = ?")) { preparedStatement.setString(1, name); ResultSet resultSet = preparedStatement.executeQuery(); while (resultSet.next()) { System.out.println(resultSet.getString("email")); } } catch (SQLException e) { e.printStackTrace(); } } }
Задача: Вставить данные в таблицу с использованием JDBC.
- Входные данные: имя и email пользователя.
- Пример кода:java
public class Main { public static void main(String[] args) { try (Connection connection = DriverManager.getConnection("jdbc:mysql://localhost:3306/mydb", "user", "password"); PreparedStatement preparedStatement = connection.prepareStatement("INSERT INTO users (name, email) VALUES (?, ?)")) { preparedStatement.setString(1, "John"); preparedStatement.setString(2, "john@example.com"); preparedStatement.executeUpdate(); System.out.println("Data inserted successfully"); } catch (SQLException e) { e.printStackTrace(); } } }
Задача: Обновить данные в таблице с помощью JDBC.
- Входные данные: обновление email пользователя по его имени.
- Пример кода:java
public class Main { public static void main(String[] args) { try (Connection connection = DriverManager.getConnection("jdbc:mysql://localhost:3306/mydb", "user", "password"); PreparedStatement preparedStatement = connection.prepareStatement("UPDATE users SET email = ? WHERE name = ?")) { preparedStatement.setString(1, "newemail@example.com"); preparedStatement.setString(2, "John"); preparedStatement.executeUpdate(); System.out.println("Data updated successfully"); } catch (SQLException e) { e.printStackTrace(); } } }
Задача: Удалить данные из таблицы с помощью JDBC.
- Входные данные: удаление пользователя по имени.
- Пример кода:java
public class Main { public static void main(String[] args) { try (Connection connection = DriverManager.getConnection("jdbc:mysql://localhost:3306/mydb", "user", "password"); PreparedStatement preparedStatement = connection.prepareStatement("DELETE FROM users WHERE name = ?")) { preparedStatement.setString(1, "John"); preparedStatement.executeUpdate(); System.out.println("Data deleted successfully"); } catch (SQLException e) { e.printStackTrace(); } } }
Задача: Использовать транзакции для выполнения нескольких операций с базой данных.
- Входные данные: вставка и обновление данных.
- Пример кода:java
public class Main { public static void main(String[] args) { try (Connection connection = DriverManager.getConnection("jdbc:mysql://localhost:3306/my
РАЗДЕЛ 1: SPRING BOOT
Базовые задачи
Задача: Создать простой Spring Boot проект с зависимостями для Web и JPA.
- Входные данные: Необходимые зависимости.
- Пример кода:java
@SpringBootApplication public class Application { public static void main(String[] args) { SpringApplication.run(Application.class, args); } }
Задача: Создать RESTful API для управления пользователями.
- Входные данные: CRUD операции.
- Пример кода:java
@RestController @RequestMapping("/users") public class UserController { @GetMapping public List<User> getAllUsers() { /* ... */ } @PostMapping public User createUser(@RequestBody User user) { /* ... */ } }
Задача: Настроить подключение к базе данных с использованием Spring Data JPA.
- Входные данные: URL базы данных, логин, пароль.
- Пример кода:yaml
spring: datasource: url: jdbc:mysql://localhost:3306/mydb username: user password: password
Задача: Создать сущность User и репозиторий для работы с ней.
- Входные данные: Сущность с полями name и email.
- Пример кода:java
@Entity public class User { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) private Long id; private String name; private String email; // Getters and setters } @Repository public interface UserRepository extends JpaRepository<User, Long> { }
Задача: Реализовать обработку ошибок в REST API.
- Входные данные: Исключения и соответствующие сообщения.
- Пример кода:java
@ControllerAdvice public class GlobalExceptionHandler { @ExceptionHandler(ResourceNotFoundException.class) public ResponseEntity<String> handleNotFound(ResourceNotFoundException ex) { return ResponseEntity.status(HttpStatus.NOT_FOUND).body(ex.getMessage()); } }
Задача: Создать тесты для контроллера с использованием MockMvc.
- Входные данные: Тестовые данные.
- Пример кода:java
@SpringBootTest @AutoConfigureMockMvc public class UserControllerTest { @Autowired private MockMvc mockMvc; @Test public void testGetAllUsers() throws Exception { mockMvc.perform(get("/users")) .andExpect(status().isOk()); } }
Задача: Использовать Spring Boot Actuator для мониторинга приложения.
- Входные данные: Включение Actuator.
- Пример кода:yaml
management: endpoints: web: exposure: include: "*"
Задача: Настроить Spring Boot DevTools для горячей перезагрузки.
- Входные данные: Зависимость в
pom.xml. - Пример кода:xml
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-devtools</artifactId> <scope>runtime</scope> <optional>true</optional> </dependency>
- Входные данные: Зависимость в
Задача: Использовать профили Spring для настройки разных сред (dev, prod).
- Входные данные: Конфигурации для каждого профиля.
- Пример кода:yaml
spring: profiles: active: dev
Задача: Создать асинхронный метод с использованием @Async.
- Входные данные: Выполнение задачи в фоновом режиме.
- Пример кода:java
@Service public class AsyncService { @Async public CompletableFuture<String> asyncMethod() { // some long-running task return CompletableFuture.completedFuture("Done"); } }
Задача: Создать Swagger документацию для REST API.
- Входные данные: Зависимости и настройки Swagger.
- Пример кода:java
@Configuration @EnableSwagger2 public class SwaggerConfig { @Bean public Docket api() { return new Docket(DocumentationType.SWAGGER_2).select().apis(RequestHandlerSelectors.any()).build(); } }
Задача: Использовать валидацию данных с помощью @Valid и @NotNull.
- Входные данные: Проверка входных данных.
- Пример кода:java
@PostMapping public User createUser(@Valid @RequestBody User user) { /* ... */ }
Задача: Настроить кэширование для методов сервиса.
- Входные данные: Аннотация @Cacheable.
- Пример кода:java
@Service public class UserService { @Cacheable("users") public User getUser(Long id) { /* ... */ } }
Задача: Реализовать фильтры для обработки запросов и ответов.
- Входные данные: Класс фильтра.
- Пример кода:java
@Component public class CustomFilter extends OncePerRequestFilter { @Override protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException { // Custom logic filterChain.doFilter(request, response); } }
Задача: Использовать AOP для логирования методов.
- Входные данные: Аннотация @Aspect.
- Пример кода:java
@Aspect @Component public class LoggingAspect { @Before("execution(* com.example.service.*.*(..))") public void logBefore(JoinPoint joinPoint) { System.out.println("Before method: " + joinPoint.getSignature().getName()); } }
Задача: Создать простое веб-приложение с Thymeleaf.
- Входные данные: HTML-шаблоны.
- Пример кода:java
@Controller public class HomeController { @GetMapping("/") public String home(Model model) { model.addAttribute("message", "Welcome to Spring Boot!"); return "home"; } }
Задача: Реализовать загрузку файлов в Spring Boot.
- Входные данные: Файл от пользователя.
- Пример кода:java
@PostMapping("/upload") public ResponseEntity<String> uploadFile(@RequestParam("file") MultipartFile file) { /* ... */ }
Задача: Реализовать механизм кэширования на основе Redis.
- Входные данные: Зависимости и настройки Redis.
- Пример кода:yaml
spring: cache: type: redis
Задача: Создать REST API с поддержкой CORS.
- Входные данные: Настройки CORS.
- Пример кода:java
@Configuration public class WebConfig implements WebMvcConfigurer { @Override public void addCorsMappings(CorsRegistry registry) { registry.addMapping("/**").allowedOrigins("http://localhost:3000"); } }
Задача: Реализовать локализацию в Spring Boot приложении.
- Входные данные: Файлы сообщений.
- Пример кода:yaml
spring: messages: basename: messages
Сложные задачи
Задача: Создать микросервис с использованием Spring Boot и Spring Cloud.
- Входные данные: Услуга регистрации пользователей.
- Пример кода:java
@SpringBootApplication @EnableEurekaClient public class UserServiceApplication { public static void main(String[] args) { SpringApplication.run(UserServiceApplication.class, args); } }
Задача: Реализовать Circuit Breaker с использованием Resilience4j.
- Входные данные: Сервис с возможностью временной недоступности.
- Пример кода:java
@Service public class UserService { @CircuitBreaker public User getUser(Long id) { /* ... */ } }
Задача: Создать API Gateway с использованием Spring Cloud Gateway.
- Входные данные: Настройки маршрутизации.
- Пример кода:yaml
spring: cloud: gateway: routes: - id: user-service uri: lb://USER-SERVICE predicates: - Path=/users/**
Задача: Настроить конфигурационный сервер с использованием Spring Cloud Config.
- Входные данные: Git-репозиторий для конфигурации.
- Пример кода:yaml
spring: cloud: config: server: git: uri: https://github.com/user/config-repo
Задача: Реализовать работу с событиями с использованием Spring Cloud Stream.
- Входные данные: Настройка обмена сообщениями.
- Пример кода:java
@EnableBinding(Processor.class) public class UserProcessor { @StreamListener(Processor.INPUT) public void handleUser(User user) { /* ... */ } }
Задача: Создать микросервис с аутентификацией и авторизацией с использованием Spring Security.
- Входные данные: Пользовательские роли.
- Пример кода:java
@EnableWebSecurity public class SecurityConfig extends WebSecurityConfigurerAdapter { @Override protected void configure(HttpSecurity http) throws Exception { http.authorizeRequests() .antMatchers("/admin/**").hasRole("ADMIN") .anyRequest().authenticated() .and() .formLogin(); } }
Задача: Реализовать JWT аутентификацию в приложении.
- Входные данные: Токен и пользовательские данные.
- Пример кода:java
@Service public class JwtTokenProvider { public String createToken(String username) { /* ... */ } public boolean validateToken(String token) { /* ... */ } }
Задача: Создать реактивное приложение с использованием Spring WebFlux.
- Входные данные: Необходимость обработки асинхронных потоков.
- Пример кода:java
@RestController public class ReactiveController { @GetMapping("/reactive-users") public Flux<User> getUsers() { /* ... */ } }
Задача: Реализовать функционал WebSocket в приложении.
- Входные данные: Сообщения для обмена.
- Пример кода:java
@Configuration @EnableWebSocketMessageBroker public class WebSocketConfig implements WebSocketMessageBrokerConfigurer { @Override public void configureMessageBroker(MessageBrokerRegistry config) { config.enableSimpleBroker("/topic"); config.setApplicationDestinationPrefixes("/app"); } }
Задача: Реализовать интеграцию с внешними API через WebClient.
- Входные данные: URL внешнего API.
- Пример кода:java
@Service public class ExternalApiService { private final WebClient webClient; public ExternalApiService(WebClient.Builder builder) { this.webClient = builder.baseUrl("https://api.example.com").build(); } public Mono<Response> getExternalData() { return webClient.get().uri("/data").retrieve().bodyToMono(Response.class); } }
РАЗДЕЛ 1: PROJECT REACTOR
Базовые задачи
Задача: Создать простой
Fluxиз списка чисел и вывести их.- Входные данные: Список чисел.
- Пример кода:java
import reactor.core.publisher.Flux; public class FluxExample { public static void main(String[] args) { Flux<Integer> numberFlux = Flux.just(1, 2, 3, 4, 5); numberFlux.subscribe(System.out::println); } }
Задача: Создать
Mono, который возвращает строку.- Входные данные: Строка "Hello, Reactor!".
- Пример кода:java
import reactor.core.publisher.Mono; public class MonoExample { public static void main(String[] args) { Mono<String> stringMono = Mono.just("Hello, Reactor!"); stringMono.subscribe(System.out::println); } }
Задача: Использовать
mapдля преобразования значений вFlux.- Входные данные: Список чисел.
- Пример кода:java
import reactor.core.publisher.Flux; public class FluxMapExample { public static void main(String[] args) { Flux<Integer> numberFlux = Flux.just(1, 2, 3); numberFlux.map(i -> i * 2) .subscribe(System.out::println); // 2, 4, 6 } }
Задача: Использовать
filterдля выбора четных чисел изFlux.- Входные данные: Список чисел.
- Пример кода:java
import reactor.core.publisher.Flux; public class FluxFilterExample { public static void main(String[] args) { Flux<Integer> numberFlux = Flux.just(1, 2, 3, 4, 5); numberFlux.filter(i -> i % 2 == 0) .subscribe(System.out::println); // 2, 4 } }
Задача: Применить оператор
flatMapдля преобразования списка строк вFlux.- Входные данные: Список строк.
- Пример кода:java
import reactor.core.publisher.Flux; public class FluxFlatMapExample { public static void main(String[] args) { Flux<String> stringFlux = Flux.just("one", "two", "three"); stringFlux.flatMap(s -> Flux.just(s.length())) .subscribe(System.out::println); // 3, 3, 5 } }
Задача: Использовать оператор
takeдля выбора первых N элементов изFlux.- Входные данные: Список чисел и значение N.
- Пример кода:java
import reactor.core.publisher.Flux; public class FluxTakeExample { public static void main(String[] args) { Flux<Integer> numberFlux = Flux.range(1, 10); numberFlux.take(5) .subscribe(System.out::println); // 1, 2, 3, 4, 5 } }
Задача: Создать
Fluxиз массива и использоватьsubscribeдля обработки элементов.- Входные данные: Массив строк.
- Пример кода:java
import reactor.core.publisher.Flux; public class FluxArrayExample { public static void main(String[] args) { String[] names = {"Alice", "Bob", "Charlie"}; Flux<String> nameFlux = Flux.fromArray(names); nameFlux.subscribe(System.out::println); // Alice, Bob, Charlie } }
Задача: Использовать оператор
reduceдля суммирования значений вFlux.- Входные данные: Список чисел.
- Пример кода:java
import reactor.core.publisher.Flux; public class FluxReduceExample { public static void main(String[] args) { Flux<Integer> numberFlux = Flux.just(1, 2, 3, 4); numberFlux.reduce(0, Integer::sum) .subscribe(System.out::println); // 10 } }
Задача: Создать комбинированный
Fluxс помощью оператораmerge.- Входные данные: Два списка чисел.
- Пример кода:java
import reactor.core.publisher.Flux; public class FluxMergeExample { public static void main(String[] args) { Flux<Integer> flux1 = Flux.just(1, 2, 3); Flux<Integer> flux2 = Flux.just(4, 5, 6); Flux<Integer> mergedFlux = Flux.merge(flux1, flux2); mergedFlux.subscribe(System.out::println); // 1, 2, 3, 4, 5, 6 } }
Задача: Реализовать простую задержку с помощью
delayElements.- Входные данные: Список чисел и время задержки.
- Пример кода:java
import reactor.core.publisher.Flux; public class FluxDelayExample { public static void main(String[] args) { Flux<Integer> numberFlux = Flux.just(1, 2, 3) .delayElements(Duration.ofSeconds(1)); numberFlux.subscribe(System.out::println); // 1, 2, 3 (с задержкой в 1 секунду) try { Thread.sleep(4000); } catch (InterruptedException e) { } } }
Задача: Использовать
onErrorResumeдля обработки ошибок вFlux.- Входные данные: Потенциально выбрасываемое исключение.
- Пример кода:java
import reactor.core.publisher.Flux; public class FluxErrorHandlingExample { public static void main(String[] args) { Flux<Integer> numberFlux = Flux.just(1, 2, 3) .concatWith(Flux.error(new RuntimeException("Error!"))) .onErrorResume(e -> Flux.just(0)); numberFlux.subscribe(System.out::println); // 1, 2, 3, 0 } }
Задача: Реализовать метод
subscribeOnдля изменения потока выполнения.- Входные данные: Параметры потока.
- Пример кода:java
import reactor.core.publisher.Flux; import reactor.core.scheduler.Schedulers; public class FluxSubscribeOnExample { public static void main(String[] args) { Flux<Integer> numberFlux = Flux.range(1, 10) .subscribeOn(Schedulers.boundedElastic()); numberFlux.subscribe(System.out::println); } }
Задача: Создать
Fluxс помощью оператораgenerate.- Входные данные: Начальное значение.
- Пример кода:java
import reactor.core.publisher.Flux; public class FluxGenerateExample { public static void main(String[] args) { Flux<Integer> generatedFlux = Flux.generate(() -> 1, (state, sink) -> { sink.next(state); return state + 1; }); generatedFlux.take(5).subscribe(System.out::println); // 1, 2, 3, 4, 5 } }
Задача: Использовать
repeatдля повторения элементов вFlux.- Входные данные: Список чисел и количество повторений.
- Пример кода:java
import reactor.core.publisher.Flux; public class FluxRepeatExample { public static void main(String[] args) { Flux<Integer> numberFlux = Flux.just(1, 2, 3); numberFlux.repeat(2).subscribe(System.out::println); // 1, 2, 3, 1, 2, 3 } }
Задача: Реализовать
Fluxс использованиемcombineLatest.- Входные данные: Два
Fluxс разными значениями. - Пример кода:java
import reactor.core.publisher.Flux; public class FluxCombineLatestExample { public static void main(String[] args) { Flux<String> flux1 = Flux.just("A", "B"); Flux<String> flux2 = Flux.just("1", "2", "3"); Flux<String> combinedFlux = Flux.combineLatest(flux1, flux
- Входные данные: Два
РАЗДЕЛ 1: REST API
Базовые задачи
Задача: Создать простой RESTful API с одним эндпоинтом, который возвращает "Hello, World!".
- Входные данные: Нет.
- Пример кода:java
import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RestController; @SpringBootApplication public class RestApiApplication { public static void main(String[] args) { SpringApplication.run(RestApiApplication.class, args); } @RestController public class HelloController { @GetMapping("/hello") public String hello() { return "Hello, World!"; } } }
Задача: Реализовать CRUD операции для сущности "Book".
- Входные данные: Создать, прочитать, обновить и удалить книгу.
- Пример кода:java
import org.springframework.web.bind.annotation.*; import java.util.ArrayList; import java.util.List; @RestController @RequestMapping("/books") public class BookController { private List<Book> books = new ArrayList<>(); @PostMapping public void addBook(@RequestBody Book book) { books.add(book); } @GetMapping public List<Book> getBooks() { return books; } @PutMapping("/{id}") public void updateBook(@PathVariable int id, @RequestBody Book book) { books.set(id, book); } @DeleteMapping("/{id}") public void deleteBook(@PathVariable int id) { books.remove(id); } } class Book { private String title; private String author; // Getters and setters }
Задача: Добавить обработку ошибок в RESTful API.
- Входные данные: Пробовать получить книгу по ID, который не существует.
- Пример кода:java
import org.springframework.http.HttpStatus; import org.springframework.web.bind.annotation.*; @RestController public class BookController { // ... @GetMapping("/{id}") public Book getBook(@PathVariable int id) { if (id < 0 || id >= books.size()) { throw new BookNotFoundException(); } return books.get(id); } @ResponseStatus(HttpStatus.NOT_FOUND) @ExceptionHandler(BookNotFoundException.class) public String handleNotFound() { return "Book not found"; } class BookNotFoundException extends RuntimeException {} }
Задача: Реализовать фильтрацию книг по автору.
- Входные данные: Параметр запроса "author".
- Пример кода:java
@GetMapping public List<Book> getBooksByAuthor(@RequestParam(required = false) String author) { if (author == null) { return books; } return books.stream().filter(b -> b.getAuthor().equals(author)).collect(Collectors.toList()); }
Задача: Реализовать пагинацию для списка книг.
- Входные данные: Параметры запроса "page" и "size".
- Пример кода:java
@GetMapping public List<Book> getBooks(@RequestParam int page, @RequestParam int size) { return books.stream() .skip(page * size) .limit(size) .collect(Collectors.toList()); }
Задача: Реализовать API для авторизации пользователя.
- Входные данные: Имя пользователя и пароль.
- Пример кода:java
@PostMapping("/login") public String login(@RequestBody User user) { if ("admin".equals(user.getUsername()) && "password".equals(user.getPassword())) { return "Login successful"; } return "Login failed"; } class User { private String username; private String password; // Getters and setters }
Задача: Реализовать кэширование данных в REST API.
- Входные данные: Запрос на получение книги.
- Пример кода:java
import org.springframework.cache.annotation.Cacheable; @Cacheable("books") @GetMapping("/{id}") public Book getBook(@PathVariable int id) { return books.get(id); // Обработка кэширования }
Задача: Реализовать поддержку CORS в REST API.
- Входные данные: Запросы с других доменов.
- Пример кода:java
@CrossOrigin(origins = "http://example.com") @GetMapping("/books") public List<Book> getBooks() { return books; }
Задача: Добавить валидацию входящих данных с использованием аннотаций.
- Входные данные: Объект книги с полями.
- Пример кода:java
import javax.validation.constraints.NotBlank; class Book { @NotBlank private String title; @NotBlank private String author; // Getters and setters } @PostMapping public void addBook(@Valid @RequestBody Book book) { books.add(book); }
Задача: Реализовать версионирование API.
- Входные данные: Запрос с заголовком версии.
- Пример кода:java
@GetMapping(value = "/books", headers = "API-Version=1") public List<Book> getBooksV1() { return books; // Версия 1 } @GetMapping(value = "/books", headers = "API-Version=2") public List<Book> getBooksV2() { return books.stream().map(b -> new BookV2(b.getTitle(), b.getAuthor())).collect(Collectors.toList()); // Версия 2 } class BookV2 { private String title; private String author; // Дополнительные поля }
Сложные задачи
Задача: Реализовать API с поддержкой Swagger для документирования.
- Входные данные: Запросы к API.
- Пример кода:java
import springfox.documentation.builders.PathSelectors; import springfox.documentation.builders.RequestHandlerSelectors; import springfox.documentation.spi.DocumentationType; import springfox.documentation.spring.web.plugins.Docket; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; @Configuration public class SwaggerConfig { @Bean public Docket api() { return new Docket(DocumentationType.SWAGGER_2) .select() .apis(RequestHandlerSelectors.any()) .paths(PathSelectors.any()) .build(); } }
Задача: Реализовать Spring Security для защиты REST API.
- Входные данные: Запросы к защищенным эндпоинтам.
- Пример кода:java
import org.springframework.context.annotation.Bean; import org.springframework.security.config.annotation.web.builders.HttpSecurity; import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity; import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter; @EnableWebSecurity public class SecurityConfig extends WebSecurityConfigurerAdapter { @Override protected void configure(HttpSecurity http) throws Exception { http.csrf().disable() .authorizeRequests() .anyRequest().authenticated() .and() .httpBasic(); } }
Задача: Реализовать тесты для REST API с использованием MockMvc.
- Входные данные: Эндпоинты API.
- Пример кода:java
import org.junit.jupiter.api.Test; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest; import org.springframework.test.web.servlet.MockMvc; import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get; import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; @WebMvcTest(BookController.class) public class BookControllerTest { @Autowired private MockMvc mockMvc; @Test public void testGetBooks() throws Exception { mockMvc.perform(get("/books")) .andExpect(status().isOk()); } }
Задача: Реализовать асинхронные запросы с использованием
@Async.- Входные данные: Запросы к API.
- Пример кода:java
import org.springframework.scheduling.annotation.Async; import org.springframework.web.bind.annotation.GetMapping; @Async @GetMapping("/async") public CompletableFuture<String> asyncEndpoint() { return CompletableFuture.completedFuture("Async Response"); }
Задача: Реализовать серверное событие (SSE) для отправки данных в реальном времени.
- Входные данные: Подписка на события.
- Пример кода:java
import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.servlet.mvc.method.annotation.SseEmitter; @GetMapping("/events") public SseEmitter handleSse() { SseEmitter emitter = new SseEmitter(); // Логика отправки событий return emitter; }
Задача: Реализовать локализацию для REST API.
- Входные данные: Запрос с заголовком локализации.
- Пример кода:java
@GetMapping("/greeting") public String greeting(@RequestHeader(name = "Accept-Language", defaultValue = "en") String language) { return "en".equals(language) ? "Hello" : "Привет"; }
Задача: Реализовать API с использованием WebFlux для реактивного программирования.
- Входные данные: Запросы к API.
- Пример кода:java
import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RestController; import reactor.core.publisher.Flux; @RestController public class ReactiveBookController { @GetMapping("/reactive-books") public Flux<Book> getReactiveBooks() { return Flux.just(new Book("Book 1"), new Book("Book 2")); } }
Задача: Реализовать фильтры для обработки запросов и ответов.
- Входные данные: Запросы к API.
- Пример кода:java
import javax.servlet.*; import javax.servlet.http.HttpServletResponse; import java.io.IOException; public class SimpleFilter implements Filter { @Override public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException { HttpServletResponse httpResponse = (HttpServletResponse) response; httpResponse.setHeader("X-Filter-Header", "value"); chain.doFilter(request, response); } }
Задача: Реализовать поддержку мультимедийных данных (изображений, видео).
- Входные данные: Загрузка файлов через API.
- Пример кода:java
import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.multipart.MultipartFile; @PostMapping("/upload") public String uploadFile(@RequestParam("file") MultipartFile file) { // Логика обработки файла return "File uploaded successfully"; }
Задача: Реализовать интеграцию с внешним API.
- Входные данные: Запросы к внешнему API.
- Пример кода:java
import org.springframework.web.client.RestTemplate; @GetMapping("/external") public String getExternalData() { RestTemplate restTemplate = new RestTemplate(); String result = restTemplate.getForObject("http://external.api/data", String.class); return result; }
РАЗДЕЛ 2: GRPC
Базовые задачи
Задача: Создать gRPC сервер, который возвращает "Hello, World!".
- Входные данные: Запрос к серверу.
- Пример кода:java
import io.grpc.Server; import io.grpc.ServerBuilder; import io.grpc.stub.StreamObserver; public class GreeterServer { public static void main(String[] args) throws IOException, InterruptedException { Server server = ServerBuilder.forPort(50051) .addService(new GreeterImpl()) .build() .start(); server.awaitTermination(); } static class GreeterImpl extends GreeterGrpc.GreeterImplBase { @Override public void sayHello(HelloRequest req, StreamObserver<HelloResponse> responseObserver) { HelloResponse reply = HelloResponse.newBuilder().setMessage("Hello, " + req.getName()).build(); responseObserver.onNext(reply); responseObserver.onCompleted(); } } }
Задача: Реализовать gRPC клиент, который отправляет имя и получает ответ.
- Входные данные: Имя для отправки.
- Пример кода:java
import io.grpc.ManagedChannel; import io.grpc.ManagedChannelBuilder; public class GreeterClient { public static void main(String[] args) { ManagedChannel channel = ManagedChannelBuilder.forAddress("localhost", 50051).usePlaintext().build(); GreeterGrpc.GreeterBlockingStub stub = GreeterGrpc.newBlockingStub(channel); HelloResponse response = stub.sayHello(HelloRequest.newBuilder().setName("World").build()); System.out.println(response.getMessage()); channel.shutdown(); } }
Задача: Реализовать gRPC сервис с двумя методами (sayHello и sayGoodbye).
- Входные данные: Имя для приветствия и прощания.
- Пример кода:java
static class GreeterImpl extends GreeterGrpc.GreeterImplBase { @Override public void sayHello(HelloRequest req, StreamObserver<HelloResponse> responseObserver) { HelloResponse reply = HelloResponse.newBuilder().setMessage("Hello, " + req.getName()).build(); responseObserver.onNext(reply); responseObserver.onCompleted(); } @Override public void sayGoodbye(HelloRequest req, StreamObserver<HelloResponse> responseObserver) { HelloResponse reply = HelloResponse.newBuilder().setMessage("Goodbye, " + req.getName()).build(); responseObserver.onNext(reply); responseObserver.onCompleted(); } }
Задача: Реализовать асинхронный gRPC метод для получения списка книг.
- Входные данные: Запрос на получение книг.
- Пример кода:java
static class BookServiceImpl extends BookServiceGrpc.BookServiceImplBase { @Override public void getBooks(Empty request, StreamObserver<BookList> responseObserver) { BookList.Builder builder = BookList.newBuilder(); builder.addBooks(Book.newBuilder().setTitle("Book 1").build()); builder.addBooks(Book.newBuilder().setTitle("Book 2").build()); responseObserver.onNext(builder.build()); responseObserver.onCompleted(); } }
Задача: Реализовать gRPC сервис с потоковым взаимодействием.
- Входные данные: Потоковые данные от клиента.
- Пример кода:java
static class ChatServiceImpl extends ChatServiceGrpc.ChatServiceImplBase { @Override public StreamObserver<Message> chat(StreamObserver<Message> responseObserver) { return new StreamObserver<Message>() { @Override public void onNext(Message message) { responseObserver.onNext(Message.newBuilder().setContent("Received: " + message.getContent()).build()); } @Override public void onError(Throwable t) {} @Override public void onCompleted() { responseObserver.onCompleted(); } }; } }
Задача: Реализовать gRPC сервис с поддержкой метаданных.
- Входные данные: Запрос с метаданными.
- Пример кода:java
@Override public void sayHello(HelloRequest req, StreamObserver<HelloResponse> responseObserver) { Metadata metadata = new Metadata(); metadata.put(Metadata.Key.of("custom-header", Metadata.ASCII_STRING_MARSHALLER), "value"); responseObserver.onNext(HelloResponse.newBuilder().setMessage("Hello, " + req.getName()).build()); responseObserver.onCompleted(); }
Задача: Реализовать аутентификацию в gRPC сервисе.
- Входные данные: Данные для аутентификации.
- Пример кода:java
@Override public void sayHello(HelloRequest req, StreamObserver<HelloResponse> responseObserver) { // Проверка аутентификации if (!isAuthenticated(req)) { responseObserver.onError(Status.UNAUTHENTICATED.withDescription("Invalid credentials").asRuntimeException()); return; } HelloResponse reply = HelloResponse.newBuilder().setMessage("Hello, " + req.getName()).build(); responseObserver.onNext(reply); responseObserver.onCompleted(); }
Задача: Реализовать тесты для gRPC сервиса с использованием JUnit.
- Входные данные: Запросы к сервису.
- Пример кода:java
@Test public void testSayHello() { GreeterGrpc.GreeterBlockingStub stub = GreeterGrpc.newBlockingStub(channel); HelloResponse response = stub.sayHello(HelloRequest.newBuilder().setName("World").build()); assertEquals("Hello, World", response.getMessage()); }
Задача: Реализовать gRPC сервис с использованием ProtoBuf для сериализации данных.
- Входные данные: Запросы с ProtoBuf.
- Пример кода:java
message Book { string title = 1; string author = 2; }
Задача: Реализовать gRPC сервис с поддержкой нескольких языков.
- Входные данные: Запрос с языком.
- Пример кода:java
@Override public void sayHello(HelloRequest req, StreamObserver<HelloResponse> responseObserver) { String message = "en".equals(req.getLanguage()) ? "Hello" : "Привет"; HelloResponse reply = HelloResponse.newBuilder().setMessage(message).build(); responseObserver.onNext(reply); responseObserver.onCompleted(); }
РАЗДЕЛ 3: API GATEWAY
Базовые задачи
Задача: Создать API Gateway с использованием Spring Cloud Gateway.
- Входные данные: Запросы к микросервисам.
- Пример кода:java
@Bean public RouteLocator customRouteLocator(RouteLocatorBuilder builder) { return builder.routes() .route("service1", r -> r.path("/service1/**").uri("http://localhost:8081")) .build(); }
Задача: Реализовать маршрутизацию запросов в API Gateway.
- Входные данные: Запросы к различным микросервисам.
- Пример кода:java
@Bean public RouteLocator customRouteLocator(RouteLocatorBuilder builder) { return builder.routes() .route("service2", r -> r.path("/service2/**").uri("http://localhost:8082")) .route("service3", r -> r.path("/service3/**").uri("http://localhost:8083")) .build(); }
Задача: Реализовать фильтры в API Gateway для обработки запросов.
- Входные данные: Запросы к API.
- Пример кода:java
@Bean public GlobalFilter customFilter() { return (exchange, chain) -> { ServerHttpRequest request = exchange.getRequest().mutate() .header("X-Header", "value") .build(); return chain.filter(exchange.mutate().request(request).build()); }; }
Задача: Реализовать авторизацию запросов в API Gateway.
- Входные данные: Запросы с токенами.
- Пример кода:java
@Bean public GlobalFilter authFilter() { return (exchange, chain) -> { String authToken = exchange.getRequest().getHeaders().getFirst("Authorization"); if (authToken == null || !isValid(authToken)) { return Mono.error(new ResponseStatusException(HttpStatus.UNAUTHORIZED)); } return chain.filter(exchange); }; }
Задача: Реализовать мониторинг и логирование запросов в API Gateway.
- Входные данные: Запросы к API.
- Пример кода:java
@Bean public GlobalFilter loggingFilter() { return (exchange, chain) -> { log.info("Request Path: {}", exchange.getRequest().getPath()); return chain.filter(exchange); }; }
Задача: Реализовать поддержку балансировки нагрузки в API Gateway.
- Входные данные: Запросы к микросервисам.
- Пример кода:java
@Bean public RouteLocator loadBalancedRoutes(RouteLocatorBuilder builder) { return builder.routes() .route("service", r -> r.path("/service/**").uri("lb://SERVICE-NAME")) .build(); }
Задача: Реализовать кэширование ответов в API Gateway.
- Входные данные: Запросы к API.
- Пример кода:java
@Bean public GlobalFilter cachingFilter() { return (exchange, chain) -> { if (isCached(exchange.getRequest())) { return exchange.getResponse().writeWith(Mono.just(getCachedResponse(exchange.getRequest()))); } return chain.filter(exchange); }; }
Задача: Реализовать API Gateway с использованием Spring Security.
- Входные данные: Запросы с аутентификацией.
- Пример кода:java
@Override protected void configure(HttpSecurity http) throws Exception { http.authorizeRequests() .antMatchers("/public/**").permitAll() .anyRequest().authenticated() .and().oauth2Login(); }
Задача: Реализовать API Gateway с использованием Zuul.
- Входные данные: Запросы к микросервисам.
- Пример кода:java
@EnableZuulProxy @SpringBootApplication public class GatewayApplication { public static void main(String[] args) { SpringApplication.run(GatewayApplication.class, args); } }
Задача: Реализовать тесты для API Gateway с использованием MockMvc.
- Входные данные: Запросы к API.
- Пример кода:java
@Test public void testApiGateway() throws Exception { mockMvc.perform(get("/service1/endpoint")) .andExpect(status().isOk()); }
Сложные задачи
Раздел 1: REST API
Задача: Реализовать REST API для управления пользователями с поддержкой аутентификации и авторизации.
- Входные данные: Запросы на создание, получение, обновление и удаление пользователей.
- Пример кода:java
@RestController @RequestMapping("/users") public class UserController { @PostMapping public User createUser(@RequestBody User user) { // Логика создания пользователя } @GetMapping("/{id}") public User getUser(@PathVariable Long id) { // Логика получения пользователя } @PutMapping("/{id}") public User updateUser(@PathVariable Long id, @RequestBody User user) { // Логика обновления пользователя } @DeleteMapping("/{id}") public void deleteUser(@PathVariable Long id) { // Логика удаления пользователя } }
Задача: Реализовать пагинацию и сортировку для списка пользователей в REST API.
- Входные данные: Параметры страницы и сортировки.
- Пример кода:java
@GetMapping public Page<User> getUsers(@RequestParam int page, @RequestParam String sort) { // Логика получения пользователей с пагинацией и сортировкой }
Задача: Реализовать документацию для REST API с использованием Swagger.
- Входные данные: Описание API.
- Пример кода:java
@Bean public Docket api() { return new Docket(DocumentationType.SWAGGER_2) .select() .apis(RequestHandlerSelectors.any()) .paths(PathSelectors.any()) .build(); }
Задача: Реализовать обработку ошибок в REST API с использованием Exception Handler.
- Входные данные: Запросы, которые могут вызвать ошибки.
- Пример кода:java
@ControllerAdvice public class GlobalExceptionHandler { @ExceptionHandler(UserNotFoundException.class) public ResponseEntity<String> handleUserNotFound(UserNotFoundException e) { return ResponseEntity.status(HttpStatus.NOT_FOUND).body(e.getMessage()); } }
Задача: Реализовать API для загрузки и обработки изображений.
- Входные данные: Загрузка изображений.
- Пример кода:java
@PostMapping("/upload") public ResponseEntity<String> uploadImage(@RequestParam("file") MultipartFile file) { // Логика обработки изображения return ResponseEntity.ok("Image uploaded successfully"); }
Задача: Реализовать API для работы с ролями пользователей.
- Входные данные: Запросы на создание и управление ролями.
- Пример кода:java
@RestController @RequestMapping("/roles") public class RoleController { @PostMapping public Role createRole(@RequestBody Role role) { // Логика создания роли } }
Задача: Реализовать API для интеграции с внешним сервисом (например, платежным).
- Входные данные: Запросы к внешнему API.
- Пример кода:java
@GetMapping("/payment/status/{transactionId}") public PaymentStatus getPaymentStatus(@PathVariable String transactionId) { // Логика запроса статуса платежа }
Задача: Реализовать тестирование REST API с использованием Spring Boot Test.
- Входные данные: Запросы к API.
- Пример кода:java
@SpringBootTest @AutoConfigureMockMvc public class UserControllerTest { @Autowired private MockMvc mockMvc; @Test public void testCreateUser() throws Exception { mockMvc.perform(post("/users") .contentType(MediaType.APPLICATION_JSON) .content("{\"name\":\"John\"}")) .andExpect(status().isCreated()); } }
Задача: Реализовать API для обработки платежей с использованием WebClient.
- Входные данные: Запросы на обработку платежей.
- Пример кода:java
@Autowired private WebClient webClient; public Mono<PaymentResponse> processPayment(PaymentRequest paymentRequest) { return webClient.post() .uri("/api/payment") .bodyValue(paymentRequest) .retrieve() .bodyToMono(PaymentResponse.class); }
Задача: Реализовать API для генерации отчетов.
- Входные данные: Запросы на создание отчетов.
- Пример кода:java
@GetMapping("/reports") public Report generateReport(@RequestParam String reportType) { // Логика генерации отчета }
Раздел 2: gRPC
Задача: Реализовать gRPC сервис для управления пользователями.
- Входные данные: Запросы на создание, получение и удаление пользователей.
- Пример кода:java
service UserService { rpc CreateUser(User) returns (UserResponse); rpc GetUser(UserId) returns (User); rpc DeleteUser(UserId) returns (Empty); }
Задача: Реализовать gRPC сервис с поддержкой аутентификации.
- Входные данные: Запросы с токенами.
- Пример кода:java
@Override public void createUser(User request, StreamObserver<UserResponse> responseObserver) { if (!isValidToken(request.getToken())) { responseObserver.onError(new StatusRuntimeException(Status.UNAUTHENTICATED)); return; } // Логика создания пользователя }
Задача: Реализовать gRPC сервис для обработки изображений.
- Входные данные: Запросы на загрузку и обработку изображений.
- Пример кода:java
service ImageService { rpc UploadImage(ImageRequest) returns (ImageResponse); }
Задача: Реализовать gRPC сервис для обработки платежей.
- Входные данные: Запросы на обработку платежей.
- Пример кода:java
service PaymentService { rpc ProcessPayment(PaymentRequest) returns (PaymentResponse); }
Задача: Реализовать gRPC сервис с поддержкой нескольких языков.
- Входные данные: Запросы с языком.
- Пример кода:java
@Override public void sayHello(HelloRequest req, StreamObserver<HelloResponse> responseObserver) { String message = "en".equals(req.getLanguage()) ? "Hello" : "Привет"; HelloResponse reply = HelloResponse.newBuilder().setMessage(message).build(); responseObserver.onNext(reply); responseObserver.onCompleted(); }
Задача: Реализовать gRPC сервис с поддержкой потоковой передачи.
- Входные данные: Запросы на получение данных.
- Пример кода:java
public void streamUsers(Empty request, StreamObserver<User> responseObserver) { // Логика отправки пользователей }
Задача: Реализовать тестирование gRPC сервиса с использованием Mockito.
- Входные данные: Запросы к gRPC сервису.
- Пример кода:java
@Test public void testCreateUser() { UserServiceGrpc.UserServiceBlockingStub stub = UserServiceGrpc.newBlockingStub(channel); UserResponse response = stub.createUser(User.newBuilder().setName("John").build()); assertEquals("Success", response.getMessage()); }
Задача: Реализовать gRPC сервис с обработкой ошибок.
- Входные данные: Запросы, которые могут вызвать ошибки.
- Пример кода:java
@Override public void getUser(UserId request, StreamObserver<User> responseObserver) { if (!userExists(request.getId())) { responseObserver.onError(new StatusRuntimeException(Status.NOT_FOUND)); return; } // Логика получения пользователя }
Задача: Реализовать gRPC сервис с поддержкой мониторинга и логирования.
- Входные данные: Запросы к gRPC сервису.
- Пример кода:java
@Override public void createUser(User request, StreamObserver<UserResponse> responseObserver) { log.info("Creating user: {}", request.getName()); // Логика создания пользователя }
Задача: Реализовать gRPC сервис с использованием ProtoBuf для сериализации данных.
- Входные данные: Запросы с ProtoBuf.
- Пример кода:java
message Book { string title = 1; string author = 2; }
Раздел 3: API Gateway
Задача: Реализовать API Gateway с поддержкой балансировки нагрузки и маршрутизации.
- Входные данные: Запросы к микросервисам.
- Пример кода:java
@Bean public RouteLocator loadBalancedRoutes(RouteLocatorBuilder builder) { return builder.routes() .route("service1", r -> r.path("/service1/**").uri("lb://SERVICE1")) .route("service2", r -> r.path("/service2/**").uri("lb://SERVICE2")) .build(); }
Задача: Реализовать API Gateway с поддержкой аутентификации и авторизации.
- Входные данные: Запросы с токенами.
- Пример кода:java
@Bean public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception { http.authorizeRequests() .antMatchers("/public/**").permitAll() .anyRequest().authenticated(); return http.build(); }
Задача: Реализовать фильтры для API Gateway.
- Входные данные: Запросы к API.
- Пример кода:java
@Bean public GlobalFilter customFilter() { return (exchange, chain) -> { ServerHttpRequest request = exchange.getRequest().mutate() .header("X-Header", "value") .build(); return chain.filter(exchange.mutate().request(request).build()); }; }
Задача: Реализовать API Gateway с использованием Zuul.
- Входные данные: Запросы к микросервисам.
- Пример кода:java
@EnableZuulProxy @SpringBootApplication public class GatewayApplication { public static void main(String[] args) { SpringApplication.run(GatewayApplication.class, args); } }
Задача: Реализовать мониторинг и логирование запросов в API Gateway.
- Входные данные: Запросы к API.
- Пример кода:java
@Bean public GlobalFilter loggingFilter() { return (exchange, chain) -> { log.info("Request: {}", exchange.getRequest().getURI()); return chain.filter(exchange); }; }
Задача: Реализовать агрегацию данных из нескольких микросервисов через API Gateway.
- Входные данные: Запросы на получение данных.
- Пример кода:java
@GetMapping("/aggregate") public Mono<AggregateResponse> aggregateData() { Mono<Data1> data1 = webClient.get().uri("/service1/data").retrieve().bodyToMono(Data1.class); Mono<Data2> data2 = webClient.get().uri("/service2/data").retrieve().bodyToMono(Data2.class); return Mono.zip(data1, data2) .map(tuple -> new AggregateResponse(tuple.getT1(), tuple.getT2())); }
Задача: Реализовать кеширование в API Gateway.
- Входные данные: Запросы к API.
- Пример кода:java
@Bean public CacheManager cacheManager() { return new ConcurrentMapCacheManager("responses"); }
Задача: Реализовать обработку ошибок в API Gateway.
- Входные данные: Запросы, которые могут вызвать ошибки.
- Пример кода:java
@ExceptionHandler(Exception.class) public ResponseEntity<String> handleException(Exception e) { return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body(e.getMessage()); }
Задача: Реализовать API Gateway с использованием Spring Cloud Gateway.
- Входные данные: Запросы к микросервисам.
- Пример кода:java
@Bean public RouteLocator customRoutes(RouteLocatorBuilder builder) { return builder.routes() .route("my_route", r -> r.path("/my_path/**") .uri("http://my_service:8080")) .build(); }
Задача: Реализовать динамическую маршрутизацию в API Gateway.
- Входные данные: Запросы к микросервисам.
- Пример кода:java
@Bean public RouteLocator dynamicRoutes(RouteLocatorBuilder builder) { return builder.routes() .route("dynamic_route", r -> r.path("/dynamic/**") .uri("http://dynamic_service")) .build(); }
РАЗДЕЛ 1: UNIT-ТЕСТИРОВАНИЕ: ИСПОЛЬЗОВАНИЕ JUNIT, TESTNG
Базовые задачи
Задача: Написать простой тест на метод сложения.
- Входные данные: Два целых числа.
- Пример кода:java
import static org.junit.jupiter.api.Assertions.assertEquals; import org.junit.jupiter.api.Test; public class CalculatorTest { @Test public void testAdd() { Calculator calculator = new Calculator(); assertEquals(5, calculator.add(2, 3)); } }
Задача: Написать тест для метода, который делит числа.
- Входные данные: Два целых числа (делитель не равен нулю).
- Пример кода:java
@Test public void testDivide() { Calculator calculator = new Calculator(); assertEquals(2, calculator.divide(6, 3)); }
Задача: Написать тест для проверки исключения деления на ноль.
- Входные данные: Два целых числа (делитель равен нулю).
- Пример кода:java
@Test public void testDivideByZero() { Calculator calculator = new Calculator(); assertThrows(ArithmeticException.class, () -> calculator.divide(1, 0)); }
Задача: Написать тест для метода, который проверяет, является ли число четным.
- Входные данные: Целое число.
- Пример кода:java
@Test public void testIsEven() { NumberUtil numberUtil = new NumberUtil(); assertTrue(numberUtil.isEven(4)); }
Задача: Написать тест для метода, который возвращает максимальное из двух чисел.
- Входные данные: Два целых числа.
- Пример кода:java
@Test public void testMax() { NumberUtil numberUtil = new NumberUtil(); assertEquals(5, numberUtil.max(5, 3)); }
Задача: Написать тест для метода, который объединяет два текста.
- Входные данные: Две строки.
- Пример кода:java
@Test public void testConcat() { StringUtil stringUtil = new StringUtil(); assertEquals("HelloWorld", stringUtil.concat("Hello", "World")); }
Задача: Написать тест для проверки, что строка пустая.
- Входные данные: Строка.
- Пример кода:java
@Test public void testIsEmpty() { StringUtil stringUtil = new StringUtil(); assertTrue(stringUtil.isEmpty("")); }
Задача: Написать тест для метода, который вычисляет факториал числа.
- Входные данные: Целое число.
- Пример кода:java
@Test public void testFactorial() { MathUtil mathUtil = new MathUtil(); assertEquals(120, mathUtil.factorial(5)); }
Задача: Написать тест для метода, который проверяет, является ли строка палиндромом.
- Входные данные: Строка.
- Пример кода:java
@Test public void testIsPalindrome() { StringUtil stringUtil = new StringUtil(); assertTrue(stringUtil.isPalindrome("madam")); }
Задача: Написать тест для метода, который возвращает длину строки.
- Входные данные: Строка.
- Пример кода:java
@Test public void testStringLength() { StringUtil stringUtil = new StringUtil(); assertEquals(5, stringUtil.length("Hello")); }
Задача: Написать тест для метода, который проверяет наличие символа в строке.
- Входные данные: Строка и символ.
- Пример кода:java
@Test public void testContains() { StringUtil stringUtil = new StringUtil(); assertTrue(stringUtil.contains("Hello", 'e')); }
Задача: Написать тест для метода, который преобразует строку в верхний регистр.
- Входные данные: Строка.
- Пример кода:java
@Test public void testToUpperCase() { StringUtil stringUtil = new StringUtil(); assertEquals("HELLO", stringUtil.toUpperCase("hello")); }
Задача: Написать тест для метода, который удаляет пробелы из строки.
- Входные данные: Строка с пробелами.
- Пример кода:java
@Test public void testTrim() { StringUtil stringUtil = new StringUtil(); assertEquals("HelloWorld", stringUtil.trim(" Hello World ")); }
Задача: Написать тест для метода, который считывает данные из файла.
- Входные данные: Путь к файлу.
- Пример кода:java
@Test public void testReadFile() { FileUtil fileUtil = new FileUtil(); assertNotNull(fileUtil.readFile("test.txt")); }
Задача: Написать тест для метода, который записывает данные в файл.
- Входные данные: Путь к файлу и данные.
- Пример кода:java
@Test public void testWriteFile() { FileUtil fileUtil = new FileUtil(); fileUtil.writeFile("test.txt", "Hello"); assertEquals("Hello", fileUtil.readFile("test.txt")); }
Сложные задачи
Задача: Написать тесты для класса с зависимостями.
- Входные данные: Класс с зависимостями.
- Пример кода:java
public class UserService { private UserRepository userRepository; public UserService(UserRepository userRepository) { this.userRepository = userRepository; } public User findUserById(Long id) { return userRepository.findById(id); } } @Test public void testFindUserById() { UserRepository mockRepo = Mockito.mock(UserRepository.class); UserService userService = new UserService(mockRepo); Mockito.when(mockRepo.findById(1L)).thenReturn(new User("John")); User user = userService.findUserById(1L); assertEquals("John", user.getName()); }
Задача: Написать тесты для методов с разными параметрами.
- Входные данные: Методы с различными параметрами.
- Пример кода:java
@ParameterizedTest @ValueSource(ints = {1, 2, 3}) public void testIsPositive(int number) { assertTrue(NumberUtil.isPositive(number)); }
Задача: Написать тесты для класса, который работает с внешним API.
- Входные данные: Запросы к API.
- Пример кода:java
@Test public void testExternalApiCall() { RestTemplate restTemplate = Mockito.mock(RestTemplate.class); Mockito.when(restTemplate.getForObject("https://api.example.com/user/1", User.class)) .thenReturn(new User("John")); UserService userService = new UserService(restTemplate); User user = userService.getUser(1L); assertEquals("John", user.getName()); }
Задача: Написать тесты для асинхронного метода.
- Входные данные: Асинхронные вызовы.
- Пример кода:java
@Test public void testAsyncMethod() throws Exception { CompletableFuture<String> future = CompletableFuture.supplyAsync(() -> "Hello"); assertEquals("Hello", future.get()); }
Задача: Написать тесты для класса с приватными методами.
- Входные данные: Класс с приватными методами.
- Пример кода:java
@Test public void testPrivateMethod() throws Exception { ReflectionTestUtils.invokeMethod(myClass, "privateMethod"); }
Задача: Написать тесты для класса с зависимостями, используя JUnit и Mockito.
- Входные данные: Класс с зависимостями.
- Пример кода:java
@Test public void testServiceWithDependency() { Service mockService = Mockito.mock(Service.class); Mockito.when(mockService.processData("input")).thenReturn("output"); MyClass myClass = new MyClass(mockService); String result = myClass.performAction("input"); assertEquals("output", result); }
Задача: Написать тесты для классов с внутренними классами.
- Входные данные: Классы с внутренними классами.
- Пример кода:java
@Test public void testInnerClass() { OuterClass outer = new OuterClass(); OuterClass.InnerClass inner = outer.new InnerClass(); assertEquals("Inner", inner.getName()); }
Задача: Написать тесты для методов с временными задержками.
- Входные данные: Методы с задержками.
- Пример кода:java
@Test public void testDelayMethod() throws InterruptedException { long start = System.currentTimeMillis(); myClass.delayMethod(); long duration = System.currentTimeMillis() - start; assertTrue(duration >= 1000); }
Задача: Написать тесты для методов, использующих файловую систему.
- Входные данные: Файловая система.
- Пример кода:java
@Test public void testFileRead() throws IOException { File file = new File("test.txt"); FileWriter writer = new FileWriter(file); writer.write("Hello"); writer.close(); String content = myClass.readFile(file.getPath()); assertEquals("Hello", content); }
Задача: Написать тесты для методов, использующих базу данных.
- Входные данные: Подключение к БД.
- Пример кода:java
@Test public void testDatabaseAccess() { UserRepository userRepository = Mockito.mock(UserRepository.class); Mockito.when(userRepository.findById(1L)).thenReturn(new User("John")); User user = userRepository.findById(1L); assertEquals("John", user.getName()); }
РАЗДЕЛ 2: МОКИРОВАНИЕ ЗАВИСИМОСТЕЙ: ИСПОЛЬЗОВАНИЕ MOCKITO
Базовые задачи
Задача: Создать мок для интерфейса.
- Входные данные: Интерфейс.
- Пример кода:java
List<String> mockList = Mockito.mock(List.class); Mockito.when(mockList.size()).thenReturn(5); assertEquals(5, mockList.size());
Задача: Создать мок и проверить вызов метода.
- Входные данные: Интерфейс.
- Пример кода:java
List<String> mockList = Mockito.mock(List.class); mockList.add("Hello"); Mockito.verify(mockList).add("Hello");
Задача: Использовать аргументы в моках.
- Входные данные: Аргументы метода.
- Пример кода:java
List<String> mockList = Mockito.mock(List.class); Mockito.when(mockList.get(0)).thenReturn("Hello"); assertEquals("Hello", mockList.get(0));
Задача: Создать мок с использованием анонимного класса.
- Входные данные: Анонимный класс.
- Пример кода:java
List<String> mockList = Mockito.mock(List.class, Mockito.withSettings().useConstructor().defaultAnswer(Mockito.CALLS_REAL_METHODS));
Задача: Использовать аргументы захвата.
- Входные данные: Аргументы метода.
- Пример кода:java
ArgumentCaptor<String> captor = ArgumentCaptor.forClass(String.class); mockList.add("Hello"); Mockito.verify(mockList).add(captor.capture()); assertEquals("Hello", captor.getValue());
Задача: Создать мок для абстрактного класса.
- Входные данные: Абстрактный класс.
- Пример кода:java
AbstractList<String> mockList = Mockito.mock(AbstractList.class); Mockito.when(mockList.size()).thenReturn(10); assertEquals(10, mockList.size());
Задача: Использовать мок для проверки состояния объекта.
- Входные данные: Состояние объекта.
- Пример кода:java
MyService myService = Mockito.mock(MyService.class); Mockito.when(myService.isAvailable()).thenReturn(true); assertTrue(myService.isAvailable());
Задача: Проверить взаимодействие между моками.
- Входные данные: Взаимодействие объектов.
- Пример кода:java
UserRepository mockRepo = Mockito.mock(UserRepository.class); UserService userService = new UserService(mockRepo); userService.createUser("John"); Mockito.verify(mockRepo).save(new User("John"));
Задача: Создать мок для класса с зависимостями.
- Входные данные: Класс с зависимостями.
- Пример кода:java
DatabaseService mockDatabase = Mockito.mock(DatabaseService.class); UserService userService = new UserService(mockDatabase); Mockito.when(mockDatabase.getUser("John")).thenReturn(new User("John"));
Задача: Использовать Mockito для тестирования исключений.
- Входные данные: Исключения.
- Пример кода:java
Mockito.when(mockDatabase.getUser("Unknown")).thenThrow(new UserNotFoundException()); assertThrows(UserNotFoundException.class, () -> userService.getUser("Unknown"));
Сложные задачи
Задача: Создать мок для сервиса и проверить взаимодействие с ним.
- Входные данные: Сервис.
- Пример кода:java
EmailService emailService = Mockito.mock(EmailService.class); UserService userService = new UserService(emailService); userService.registerUser("John"); Mockito.verify(emailService).sendWelcomeEmail("John");
Задача: Создать мок для класса с состоянием и проверить изменения.
- Входные данные: Класс с состоянием.
- Пример кода:java
User user = new User("John"); Mockito.when(mockUserService.getUser("John")).thenReturn(user); user.setActive(true); assertTrue(user.isActive());
Задача: Проверить порядок вызовов методов.
- Входные данные: Вызовы методов.
- Пример кода:java
Mockito.verify(mockRepo).save(new User("John")); Mockito.verify(mockRepo).sendNotification("John");
Задача: Создать мок с использованием spy.
- Входные данные: Объект.
- Пример кода:java
UserService userService = new UserService(); UserService spyService = Mockito.spy(userService); Mockito.doReturn(new User("Jane")).when(spyService).getUser("Jane");
Задача: Использовать стейты в моках.
- Входные данные: Стейты.
- Пример кода:java
when(mockList.size()).thenReturn(0).thenReturn(1); assertEquals(0, mockList.size()); assertEquals(1, mockList.size());
Задача: Создать мок для класса с несколькими зависимостями.
- Входные данные: Класс с несколькими зависимостями.
- Пример кода:java
MyService service = new MyService(mockRepo, mockEmailService); service.process(); verify(mockRepo).save(any()); verify(mockEmailService).sendEmail(any());
Задача: Создать тест для асинхронного метода с использованием мока.
- Входные данные: Асинхронный метод.
- Пример кода:java
CompletableFuture<String> future = Mockito.mock(CompletableFuture.class); Mockito.when(future.get()).thenReturn("result"); assertEquals("result", future.get());
Задача: Проверить вызовы в нескольких потоках.
- Входные данные: Многопоточность.
- Пример кода:java
ExecutorService executor = Executors.newFixedThreadPool(2); executor.submit(() -> userService.createUser("John")); executor.submit(() -> userService.createUser("Jane")); Mockito.verify(mockRepo, Mockito.times(2)).save(any());
Задача: Создать тест с использованием аргументов для метода, вызываемого несколько раз.
- Входные данные: Аргументы.
- Пример кода:java
mockList.add("Hello"); mockList.add("World"); Mockito.verify(mockList, Mockito.times(2)).add(anyString());
Задача: Использовать мок для проверки взаимодействия с реальным объектом.
- Входные данные: Реальный объект.
- Пример кода:java
UserService userService = new UserService(new RealRepository()); User user = Mockito.mock(User.class); userService.register(user); Mockito.verify(user).notify();
РАЗДЕЛ 3: ИНТЕГРАЦИОННЫЕ ТЕСТЫ
Базовые задачи
Задача: Настроить интеграционный тест для простого контроллера Spring.
- Входные данные: Контроллер Spring.
- Пример кода:java
@SpringBootTest(webEnvironment = WebEnvironment.RANDOM_PORT) public class MyControllerIntegrationTest { @Autowired private TestRestTemplate restTemplate; @Test public void testGetEndpoint() { ResponseEntity<String> response = restTemplate.getForEntity("/api/data", String.class); assertEquals(HttpStatus.OK, response.getStatusCode()); } }
Задача: Проверить интеграцию с базой данных.
- Входные данные: База данных.
- Пример кода:java
@SpringBootTest public class UserRepositoryIntegrationTest { @Autowired private UserRepository userRepository; @Test public void testUserSave() { User user = new User("John"); userRepository.save(user); assertEquals(1, userRepository.count()); } }
Задача: Проверить взаимодействие нескольких сервисов.
- Входные данные: Несколько сервисов.
- Пример кода:java
@SpringBootTest public class UserServiceIntegrationTest { @Autowired private UserService userService; @Test public void testUserCreation() { userService.createUser("John"); assertTrue(userService.userExists("John")); } }
Задача: Проверить интеграцию с внешним API.
- Входные данные: Внешний API.
- Пример кода:java
@SpringBootTest public class ExternalApiIntegrationTest { @Autowired private ExternalApiService externalApiService; @Test public void testGetDataFromApi() { String data = externalApiService.getData(); assertNotNull(data); } }
Задача: Проверить обработку ошибок в интеграционном тесте.
- Входные данные: Исключения.
- Пример кода:java
@SpringBootTest public class ErrorHandlingIntegrationTest { @Autowired private UserService userService; @Test public void testUserNotFound() { assertThrows(UserNotFoundException.class, () -> userService.getUser("Unknown")); } }
Задача: Проверить работу с асинхронными методами.
- Входные данные: Асинхронные методы.
- Пример кода:java
@SpringBootTest public class AsyncServiceIntegrationTest { @Autowired private AsyncService asyncService; @Test public void testAsyncMethod() throws Exception { CompletableFuture<String> future = asyncService.performAsync(); assertEquals("result", future.get()); } }
Задача: Проверить взаимодействие с кешем.
- Входные данные: Кеширование.
- Пример кода:java
@SpringBootTest public class CacheIntegrationTest { @Autowired private UserService userService; @Test public void testCacheUsage() { userService.createUser("John"); User user1 = userService.getUser("John"); User user2 = userService.getUser("John"); assertSame(user1, user2); } }
Задача: Проверить работу с различными профилями.
- Входные данные: Профили.
- Пример кода:java
@ActiveProfiles("test") @SpringBootTest public class ProfileIntegrationTest { @Autowired private MyService myService; @Test public void testProfileSpecific() { assertEquals("Test Value", myService.getValue()); } }
Задача: Проверить обработку транзакций.
- Входные данные: Транзакции.
- Пример кода:java
@SpringBootTest public class TransactionIntegrationTest { @Autowired private UserService userService; @Test @Transactional public void testTransactional() { userService.createUser("John"); assertEquals(1, userService.getUserCount()); } }
Задача: Проверить взаимодействие с файловой системой.
- Входные данные: Файлы.
- Пример кода:java
@SpringBootTest public class FileIntegrationTest { @Autowired private FileService fileService; @Test public void testFileRead() throws IOException { String content = fileService.readFile("test.txt"); assertEquals("Hello", content); } }
Сложные задачи
Задача: Проверить работу с несколькими БД.
- Входные данные: Несколько баз данных.
- Пример кода:java
@SpringBootTest public class MultiDbIntegrationTest { @Autowired private UserRepository userRepository; @Autowired private OrderRepository orderRepository; @Test public void testMultiDbIntegration() { userRepository.save(new User("John")); orderRepository.save(new Order("Order1")); assertEquals(1, userRepository.count()); assertEquals(1, orderRepository.count()); } }
Задача: Проверить асинхронную обработку данных.
- Входные данные: Асинхронные методы.
- Пример кода:java
@SpringBootTest public class AsyncDataIntegrationTest { @Autowired private DataService dataService; @Test public void testAsyncDataProcessing() throws Exception { CompletableFuture<Void> future = dataService.processDataAsync(); future.get(); assertTrue(dataService.isProcessed()); } }
Задача: Проверить интеграцию с внешним REST API.
- Входные данные: Внешний API.
- Пример кода:java
@SpringBootTest public class ExternalApiIntegrationTest { @Autowired private ApiService apiService; @Test public void testExternalApiCall() { Response response = apiService.callExternalApi(); assertEquals(200, response.getStatusCode()); } }
Задача: Проверить работу с несколькими сервисами.
- Входные данные: Несколько сервисов.
- Пример кода:java
@SpringBootTest public class MultiServiceIntegrationTest { @Autowired private UserService userService; @Autowired private NotificationService notificationService; @Test public void testMultiServiceInteraction() { userService.createUser("John"); notificationService.sendNotification("User created"); assertTrue(notificationService.hasSent("User created")); } }
Задача: Проверить обработку событий.
- Входные данные: События.
- Пример кода:java
@SpringBootTest public class EventIntegrationTest { @Autowired private ApplicationEventPublisher publisher; @Test public void testEventPublishing() { publisher.publishEvent(new UserCreatedEvent(this, "John")); // Проверка, что событие было обработано } }
Задача: Проверить обработку очередей сообщений.
- Входные данные: Очереди сообщений.
- Пример кода:java
@SpringBootTest public class MessageQueueIntegrationTest { @Autowired private MessageQueueService messageQueueService; @Test public void testMessageProcessing() { messageQueueService.sendMessage("Test message"); assertTrue(messageQueueService.hasProcessed("Test message")); } }
Задача: Проверить обработку транзакций с несколькими сервисами.
- Входные данные: Транзакции.
- Пример кода:java
@SpringBootTest public class TransactionMultiServiceTest { @Autowired private UserService userService; @Autowired private OrderService orderService; @Test @Transactional public void testTransactionWithMultipleServices() { userService.createUser("John"); orderService.createOrder("Order1"); // Проверка, что оба объекта были сохранены } }
Задача: Проверить обработку ошибок в нескольких сервисах.
- Входные данные: Исключения.
- Пример кода:java
@SpringBootTest public class ErrorHandlingMultiServiceTest { @Autowired private UserService userService; @Autowired private OrderService orderService; @Test public void testErrorHandling() { assertThrows(UserNotFoundException.class, () -> userService.getUser("Unknown")); assertThrows(OrderNotFoundException.class, () -> orderService.getOrder("Unknown")); } }
Задача: Проверить интеграцию с несколькими внешними сервисами.
- Входные данные: Внешние сервисы.
- Пример кода:java
@SpringBootTest public class ExternalServiceIntegrationTest { @Autowired private ServiceA serviceA; @Autowired private ServiceB serviceB; @Test public void testMultipleExternalServices() { Response responseA = serviceA.call(); Response responseB = serviceB.call(); assertEquals(200, responseA.getStatusCode()); assertEquals(200, responseB.getStatusCode()); } }
Задача: Проверить взаимодействие с кэшем в нескольких сервисах.
- Входные данные: Кеширование.
- Пример кода:java
@SpringBootTest public class CacheMultiServiceTest { @Autowired private UserService userService; @Autowired private OrderService orderService; @Test public void testCacheInMultipleServices() { userService.createUser("John"); orderService.createOrder("Order1"); User user1 = userService.getUser("John"); User user2 = userService.getUser("John"); assertSame(user1, user2); } }
1. РЕАЛИЗАЦИЯ БАЗОВЫХ СТРУКТУР ДАННЫХ: СТЕК, ОЧЕРЕДЬ, ДЕРЕВО, ГРАФ
Базовые задачи
Задача: Реализовать стек на основе массива.
- Входные данные: Методы push, pop, peek.
- Пример кода:java
class Stack { private int[] arr; private int top; private int capacity; public Stack(int size) { arr = new int[size]; capacity = size; top = -1; } public void push(int x) { if (top == capacity - 1) { System.out.println("Stack Overflow"); return; } arr[++top] = x; } public int pop() { if (top == -1) { System.out.println("Stack Underflow"); return -1; } return arr[top--]; } public int peek() { if (top == -1) { System.out.println("Stack is empty"); return -1; } return arr[top]; } }
Задача: Реализовать очередь на основе массива.
- Входные данные: Методы enqueue, dequeue, front.
- Пример кода:java
class Queue { private int[] arr; private int front, rear, capacity; public Queue(int size) { arr = new int[size]; capacity = size; front = 0; rear = -1; } public void enqueue(int x) { if (rear == capacity - 1) { System.out.println("Queue is full"); return; } arr[++rear] = x; } public int dequeue() { if (front > rear) { System.out.println("Queue is empty"); return -1; } return arr[front++]; } public int front() { if (front > rear) { System.out.println("Queue is empty"); return -1; } return arr[front]; } }
Задача: Реализовать бинарное дерево поиска (BST).
- Входные данные: Методы insert, search, delete.
- Пример кода:java
class Node { int key; Node left, right; public Node(int item) { key = item; left = right = null; } } class BST { Node root; public void insert(int key) { root = insertRec(root, key); } private Node insertRec(Node root, int key) { if (root == null) { root = new Node(key); return root; } if (key < root.key) { root.left = insertRec(root.left, key); } else if (key > root.key) { root.right = insertRec(root.right, key); } return root; } }
Задача: Реализовать граф с помощью списков смежности.
- Входные данные: Метод addEdge.
- Пример кода:java
import java.util.LinkedList; class Graph { private int V; // Количество вершин private LinkedList<Integer>[] adjList; public Graph(int v) { V = v; adjList = new LinkedList[v]; for (int i = 0; i < v; i++) { adjList[i] = new LinkedList<>(); } } public void addEdge(int source, int destination) { adjList[source].add(destination); adjList[destination].add(source); // Для неориентированного графа } }
Задача: Реализовать стек на основе LinkedList.
- Входные данные: Методы push, pop, peek.
- Пример кода:java
class Node { int data; Node next; Node(int data) { this.data = data; } } class LinkedListStack { private Node top; public void push(int x) { Node newNode = new Node(x); newNode.next = top; top = newNode; } public int pop() { if (top == null) { System.out.println("Stack is empty"); return -1; } int data = top.data; top = top.next; return data; } public int peek() { if (top == null) { System.out.println("Stack is empty"); return -1; } return top.data; } }
Задача: Реализовать очередь на основе LinkedList.
- Входные данные: Методы enqueue, dequeue, front.
- Пример кода:java
class LinkedListNode { int data; LinkedListNode next; LinkedListNode(int data) { this.data = data; } } class LinkedListQueue { private LinkedListNode front, rear; public LinkedListQueue() { front = rear = null; } public void enqueue(int x) { LinkedListNode newNode = new LinkedListNode(x); if (rear == null) { front = rear = newNode; return; } rear.next = newNode; rear = newNode; } public int dequeue() { if (front == null) { System.out.println("Queue is empty"); return -1; } int data = front.data; front = front.next; if (front == null) { rear = null; } return data; } public int front() { if (front == null) { System.out.println("Queue is empty"); return -1; } return front.data; } }
Задача: Реализовать обход бинарного дерева в глубину (DFS).
- Входные данные: Метод traverse.
- Пример кода:java
class BinaryTree { Node root; public void DFS(Node node) { if (node == null) return; System.out.print(node.key + " "); DFS(node.left); DFS(node.right); } }
Задача: Реализовать обход бинарного дерева в ширину (BFS).
- Входные данные: Метод traverse.
- Пример кода:java
import java.util.LinkedList; import java.util.Queue; class BinaryTree { Node root; public void BFS() { Queue<Node> queue = new LinkedList<>(); queue.add(root); while (!queue.isEmpty()) { Node node = queue.poll(); System.out.print(node.key + " "); if (node.left != null) queue.add(node.left); if (node.right != null) queue.add(node.right); } } }
Задача: Реализовать двусвязный список.
- Входные данные: Методы добавления, удаления.
- Пример кода:java
class DoublyNode { int data; DoublyNode next; DoublyNode prev; DoublyNode(int data) { this.data = data; } } class DoublyLinkedList { DoublyNode head; public void add(int data) { DoublyNode newNode = new DoublyNode(data); if (head == null) { head = newNode; return; } DoublyNode last = head; while (last.next != null) { last = last.next; } last.next = newNode; newNode.prev = last; } }
Задача: Реализовать кольцевую очередь.
- Входные данные: Методы enqueue, dequeue.
- Пример кода:java
class CircularQueue { private int[] arr; private int front, rear, capacity; public CircularQueue(int size) { arr = new int[size]; capacity = size; front = rear = 0; } public void enqueue(int x) { if ((rear + 1) % capacity == front) { System.out.println("Queue is full"); return; } arr[rear] = x; rear = (rear + 1) % capacity; } public int dequeue() { if (front == rear) { System.out.println("Queue is empty"); return -1; } int data = arr[front]; front = (front + 1) % capacity; return data; } }
Задача: Реализовать структуру данных "множество" с использованием дерева.
- Входные данные: Методы add, contains.
- Пример кода:java
class Set { private BST bst; public Set() { bst = new BST(); } public void add(int value) { bst.insert(value); } public boolean contains(int value) { return containsRec(bst.root, value); } private boolean containsRec(Node node, int value) { if (node == null) return false; if (node.key == value) return true; return value < node.key ? containsRec(node.left, value) : containsRec(node.right, value); } }
Задача: Реализовать бинарное дерево с подсчетом высоты.
- Входные данные: Метод height.
- Пример кода:java
class BinaryTree { Node root; public int height(Node node) { if (node == null) return -1; int leftHeight = height(node.left); int rightHeight = height(node.right); return Math.max(leftHeight, rightHeight) + 1; } }
Задача: Реализовать бинарное дерево с подсчетом листьев.
- Входные данные: Метод countLeaves.
- Пример кода:java
class BinaryTree { Node root; public int countLeaves(Node node) { if (node == null) return 0; if (node.left == null && node.right == null) return 1; return countLeaves(node.left) + countLeaves(node.right); } }
Задача: Реализовать приоритетную очередь.
- Входные данные: Методы enqueue, dequeue.
- Пример кода:java
import java.util.PriorityQueue; class PriorityQueueExample { private PriorityQueue<Integer> queue = new PriorityQueue<>(); public void enqueue(int x) { queue.add(x); } public int dequeue() { return queue.poll(); } }
Задача: Реализовать "число Фибоначчи" с помощью рекурсивного дерева.
- Входные данные: Метод fib.
- Пример кода:java
class Fibonacci { public int fib(int n) { if (n <= 1) return n; return fib(n - 1) + fib(n - 2); } }
Сложные задачи
Задача: Реализовать динамический массив (ArrayList).
- Входные данные: Методы add, remove, get.
- Пример кода:java
class DynamicArray { private int[] arr; private int size; private int capacity; public DynamicArray() { capacity = 2; arr = new int[capacity]; size = 0; } public void add(int x) { if (size == capacity) { resize(); } arr[size++] = x; } private void resize() { capacity *= 2; int[] newArr = new int[capacity]; System.arraycopy(arr, 0, newArr, 0, size); arr = newArr; } public int get(int index) { if (index < 0 || index >= size) { throw new IndexOutOfBoundsException(); } return arr[index]; } public void remove(int index) { if (index < 0 || index >= size) { throw new IndexOutOfBoundsException(); } for (int i = index; i < size - 1; i++) { arr[i] = arr[i + 1]; } size--; } }
Задача: Реализовать структуру данных "хеш-таблица".
- Входные данные: Методы put, get.
- Пример кода:java
import java.util.LinkedList; class HashTable { private LinkedList<Entry>[] table; class Entry { String key; String value; Entry(String key, String value) { this.key = key; this.value = value; } } public HashTable(int size) { table = new LinkedList[size]; for (int i = 0; i < size; i++) { table[i] = new LinkedList<>(); } } public void put(String key, String value) { int index = key.hashCode() % table.length; for (Entry entry : table[index]) { if (entry.key.equals(key)) { entry.value = value; return; } } table[index].add(new Entry(key, value)); } public String get(String key) { int index = key.hashCode() % table.length; for (Entry entry : table[index]) { if (entry.key.equals(key)) { return entry.value; } } return null; } }
Задача: Реализовать алгоритм QuickSort.
- Входные данные: Массив чисел.
- Пример кода:java
class QuickSort { public void sort(int[] arr, int low, int high) { if (low < high) { int pi = partition(arr, low, high); sort(arr, low, pi - 1); sort(arr, pi + 1, high); } } private int partition(int[] arr, int low, int high) { int pivot = arr[high]; int i = (low - 1); for (int j = low; j < high; j++) { if (arr[j] < pivot) { i++; int temp = arr[i]; arr[i] = arr[j]; arr[j] = temp; } } int temp = arr[i + 1]; arr[i + 1] = arr[high]; arr[high] = temp; return i + 1; } }
Задача: Реализовать алгоритм MergeSort.
- Входные данные: Массив чисел.
- Пример кода:java
class MergeSort { public void sort(int[] arr, int left, int right) { if (left < right) { int mid = (left + right) / 2; sort(arr, left, mid); sort(arr, mid + 1, right); merge(arr, left, mid, right); } } private void merge(int[] arr, int left, int mid, int right) { int n1 = mid - left + 1; int n2 = right - mid; int[] L = new int[n1]; int[] R = new int[n2]; System.arraycopy(arr, left, L, 0, n1); System.arraycopy(arr, mid + 1, R, 0, n2); int i = 0, j = 0, k = left; while (i < n1 && j < n2) { if (L[i] <= R[j]) { arr[k++] = L[i++]; } else { arr[k++] = R[j++]; } } while (i < n1) { arr[k++] = L[i++]; } while (j < n2) { arr[k++] = R[j++]; } } }
Задача: Реализовать алгоритм бинарного поиска.
- Входные данные: Отсортированный массив и элемент для поиска.
- Пример кода:java
class BinarySearch { public int search(int[] arr, int target) { int left = 0, right = arr.length - 1; while (left <= right) { int mid = left + (right - left) / 2; if (arr[mid] == target) return mid; if (arr[mid] < target) left = mid + 1; else right = mid - 1; } return -1; // Элемент не найден } }
Задача: Реализовать алгоритм Дейкстры для поиска кратчайшего пути в графе.
- Входные данные: Граф и начальная вершина.
- Пример кода:java
import java.util.*; class Dijkstra { private int V; private List<List<int[]>> adj; public Dijkstra(int v) { V = v; adj = new ArrayList<>(v); for (int i = 0; i < v; i++) { adj.add(new ArrayList<>()); } } public void addEdge(int u, int v, int w) { adj.get(u).add(new int[] { v, w }); } public int[] dijkstra(int start) { PriorityQueue<int[]> pq = new PriorityQueue<>(Comparator.comparingInt(a -> a[1])); pq.add(new int[] { start, 0 }); int[] dist = new int[V]; Arrays.fill(dist, Integer.MAX_VALUE); dist[start] = 0; while (!pq.isEmpty()) { int[] current = pq.poll(); int u = current[0]; int d = current[1]; if (d > dist[u]) continue; for (int[] edge : adj.get(u)) { int v = edge[0]; int weight = edge[1]; if (dist[u] + weight < dist[v]) { dist[v] = dist[u] + weight; pq.add(new int[] { v, dist[v] }); } } } return dist; } }
Задача: Реализовать алгоритм A* для поиска кратчайшего пути в графе.
- Входные данные: Граф, начальная и конечная вершина.
- Пример кода:java
import java.util.*; class AStar { private static class Node { int id; int g; // стоимость пути от начальной вершины int h; // оценочная стоимость до конечной вершины Node(int id, int g, int h) { this.id = id; this.g = g; this.h = h; } int f() { return g + h; } } private List<List<int[]>> graph; private int[] heuristic; public AStar(int nodes, int[] heuristic) { graph = new ArrayList<>(nodes); for (int i = 0; i < nodes; i++) { graph.add(new ArrayList<>()); } this.heuristic = heuristic; } public void addEdge(int u, int v, int weight) { graph.get(u).add(new int[]{v, weight}); } public List<Integer> aStar(int start, int goal) { PriorityQueue<Node> openSet = new PriorityQueue<>(Comparator.comparingInt(Node::f)); boolean[] closedSet = new boolean[graph.size()]; Map<Integer, Integer> cameFrom = new HashMap<>(); Map<Integer, Integer> gScore = new HashMap<>(); Map<Integer, Integer> fScore = new HashMap<>(); gScore.put(start, 0); fScore.put(start, heuristic[start]); openSet.add(new Node(start, gScore.get(start), heuristic[start])); while (!openSet.isEmpty()) { Node current = openSet.poll(); if (current.id == goal) { return reconstructPath(cameFrom, current.id); } closedSet[current.id] = true; for (int[] neighbor : graph.get(current.id)) { int neighborId = neighbor[0]; int weight = neighbor[1]; if (closedSet[neighborId]) continue; int tentativeGScore = gScore.getOrDefault(current.id, Integer.MAX_VALUE) + weight; if (tentativeGScore < gScore.getOrDefault(neighborId, Integer.MAX_VALUE)) { cameFrom.put(neighborId, current.id); gScore.put(neighborId, tentativeGScore); fScore.put(neighborId, tentativeGScore + heuristic[neighborId]); openSet.add(new Node(neighborId, tentativeGScore, heuristic[neighborId])); } } } return Collections.emptyList(); // Путь не найден } private List<Integer> reconstructPath(Map<Integer, Integer> cameFrom, int current) { List<Integer> totalPath = new ArrayList<>(); while (cameFrom.containsKey(current)) { totalPath.add(current); current = cameFrom.get(current); } Collections.reverse(totalPath); return totalPath; } }
Задача: Реализовать обход графа в ширину (BFS).
- Входные данные: Граф и начальная вершина.
- Пример кода:java
import java.util.*; class BFS { private List<List<Integer>> graph; public BFS(int nodes) { graph = new ArrayList<>(nodes); for (int i = 0; i < nodes; i++) { graph.add(new ArrayList<>()); } } public void addEdge(int u, int v) { graph.get(u).add(v); graph.get(v).add(u); // если неориентированный граф } public void bfs(int start) { boolean[] visited = new boolean[graph.size()]; Queue<Integer> queue = new LinkedList<>(); queue.add(start); visited[start] = true; while (!queue.isEmpty()) { int node = queue.poll(); System.out.print(node + " "); for (int neighbor : graph.get(node)) { if (!visited[neighbor]) { visited[neighbor] = true; queue.add(neighbor); } } } } }
Задача: Реализовать обход графа в глубину (DFS).
- Входные данные: Граф и начальная вершина.
- Пример кода:java
import java.util.*; class DFS { private List<List<Integer>> graph; public DFS(int nodes) { graph = new ArrayList<>(nodes); for (int i = 0; i < nodes; i++) { graph.add(new ArrayList<>()); } } public void addEdge(int u, int v) { graph.get(u).add(v); graph.get(v).add(u); // если неориентированный граф } public void dfs(int start) { boolean[] visited = new boolean[graph.size()]; dfsUtil(start, visited); } private void dfsUtil(int node, boolean[] visited) { visited[node] = true; System.out.print(node + " "); for (int neighbor : graph.get(node)) { if (!visited[neighbor]) { dfsUtil(neighbor, visited); } } } }
Задача: Реализовать алгоритм поиска в глубину с отслеживанием времени выполнения.
- Входные данные: Граф и начальная вершина.
- Пример кода:java
import java.util.*; class TimedDFS { private List<List<Integer>> graph; public TimedDFS(int nodes) { graph = new ArrayList<>(nodes); for (int i = 0; i < nodes; i++) { graph.add(new ArrayList<>()); } } public void addEdge(int u, int v) { graph.get(u).add(v); graph.get(v).add(u); // если неориентированный граф } public void dfs(int start) { long startTime = System.nanoTime(); boolean[] visited = new boolean[graph.size()]; dfsUtil(start, visited); long endTime = System.nanoTime(); System.out.println("\nВремя выполнения: " + (endTime - startTime) + " нс"); } private void dfsUtil(int node, boolean[] visited) { visited[node] = true; System.out.print(node + " "); for (int neighbor : graph.get(node)) { if (!visited[neighbor]) { dfsUtil(neighbor, visited); } } } }
SSL И ШИФРОВАНИЕ
Базовые задачи
Задача: Настроить HTTPS сервер с использованием самоподписанного сертификата.
- Входные данные: Путь к сертификату и ключу.
- Пример кода:java
import javax.net.ssl.*; import java.io.*; import java.security.KeyStore; public class HttpsServer { public static void main(String[] args) throws Exception { char[] password = "password".toCharArray(); KeyStore keyStore = KeyStore.getInstance("JKS"); keyStore.load(new FileInputStream("keystore.jks"), password); KeyManagerFactory kmf = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm()); kmf.init(keyStore, password); SSLContext sslContext = SSLContext.getInstance("TLS"); sslContext.init(kmf.getKeyManagers(), null, null); SSLServerSocketFactory factory = sslContext.getServerSocketFactory(); SSLServerSocket serverSocket = (SSLServerSocket) factory.createServerSocket(8443); System.out.println("HTTPS Server started on port 8443"); while (true) { SSLSocket socket = (SSLSocket) serverSocket.accept(); handleClient(socket); } } private static void handleClient(SSLSocket socket) throws IOException { PrintWriter out = new PrintWriter(socket.getOutputStream(), true); out.println("HTTP/1.1 200 OK"); out.println("Content-Type: text/plain"); out.println(); out.println("Hello, secure world!"); out.flush(); socket.close(); } }
Задача: Зашифровать строку с использованием алгоритма AES.
- Входные данные: Исходная строка и ключ.
- Пример кода:java
import javax.crypto.Cipher; import javax.crypto.KeyGenerator; import javax.crypto.SecretKey; import javax.crypto.spec.SecretKeySpec; import java.util.Base64; public class AesEncryption { public static void main(String[] args) throws Exception { String originalString = "Hello, World!"; String key = "1234567890123456"; // 16-byte key for AES-128 SecretKeySpec secretKey = new SecretKeySpec(key.getBytes(), "AES"); Cipher cipher = Cipher.getInstance("AES"); cipher.init(Cipher.ENCRYPT_MODE, secretKey); byte[] encrypted = cipher.doFinal(originalString.getBytes()); System.out.println("Encrypted: " + Base64.getEncoder().encodeToString(encrypted)); } }
Задача: Расшифровать строку, зашифрованную с использованием алгоритма AES.
- Входные данные: Зашифрованная строка и ключ.
- Пример кода:java
import javax.crypto.Cipher; import javax.crypto.spec.SecretKeySpec; import java.util.Base64; public class AesDecryption { public static void main(String[] args) throws Exception { String encryptedString = "ENCRYPTED_STRING_HERE"; // вставьте зашифрованную строку String key = "1234567890123456"; // 16-byte key for AES-128 SecretKeySpec secretKey = new SecretKeySpec(key.getBytes(), "AES"); Cipher cipher = Cipher.getInstance("AES"); cipher.init(Cipher.DECRYPT_MODE, secretKey); byte[] decrypted = cipher.doFinal(Base64.getDecoder().decode(encryptedString)); System.out.println("Decrypted: " + new String(decrypted)); } }
Задача: Создать самоподписанный сертификат с помощью Java Keytool.
- Входные данные: Параметры для генерации сертификата.
- Пример команды:bash
keytool -genkeypair -alias mycert -keyalg RSA -keystore keystore.jks -storepass password -validity 365
Задача: Проверить сертификат SSL сервера.
- Входные данные: URL-адрес сервера.
- Пример кода:java
import javax.net.ssl.HttpsURLConnection; import java.net.URL; public class CheckSslCertificate { public static void main(String[] args) throws Exception { String url = "https://example.com"; HttpsURLConnection connection = (HttpsURLConnection) new URL(url).openConnection(); connection.connect(); System.out.println("Certificate: " + connection.getServerCertificates()); } }
Задача: Зашифровать файл с использованием алгоритма AES.
- Входные данные: Путь к файлу и ключ.
- Пример кода:java
import javax.crypto.Cipher; import javax.crypto.spec.SecretKeySpec; import java.io.FileInputStream; import java.io.FileOutputStream; public class AesFileEncryption { public static void main(String[] args) throws Exception { String key = "1234567890123456"; // 16-byte key for AES-128 SecretKeySpec secretKey = new SecretKeySpec(key.getBytes(), "AES"); Cipher cipher = Cipher.getInstance("AES"); cipher.init(Cipher.ENCRYPT_MODE, secretKey); try (FileInputStream fis = new FileInputStream("plain.txt"); FileOutputStream fos = new FileOutputStream("encrypted.txt")) { byte[] input = new byte[64]; int bytesRead; while ((bytesRead = fis.read(input)) != -1) { byte[] output = cipher.update(input, 0, bytesRead); if (output != null) { fos.write(output); } } byte[] outputBytes = cipher.doFinal(); if (outputBytes != null) { fos.write(outputBytes); } } } }
Задача: Расшифровать файл, зашифрованный с использованием алгоритма AES.
- Входные данные: Путь к зашифрованному файлу и ключ.
- Пример кода:java
import javax.crypto.Cipher; import javax.crypto.spec.SecretKeySpec; import java.io.FileInputStream; import java.io.FileOutputStream; public class AesFileDecryption { public static void main(String[] args) throws Exception { String key = "1234567890123456"; // 16-byte key for AES-128 SecretKeySpec secretKey = new SecretKeySpec(key.getBytes(), "AES"); Cipher cipher = Cipher.getInstance("AES"); cipher.init(Cipher.DECRYPT_MODE, secretKey); try (FileInputStream fis = new FileInputStream("encrypted.txt"); FileOutputStream fos = new FileOutputStream("decrypted.txt")) { byte[] input = new byte[64]; int bytesRead; while ((bytesRead = fis.read(input)) != -1) { byte[] output = cipher.update(input, 0, bytesRead); if (output != null) { fos.write(output); } } byte[] outputBytes = cipher.doFinal(); if (outputBytes != null) { fos.write(outputBytes); } } } }
Задача: Создать SSLContext с доверенным сертификатом.
- Входные данные: Путь к файлу с сертификатом.
- Пример кода:java
import javax.net.ssl.SSLContext; import java.security.KeyStore; public class CustomSSLContext { public static void main(String[] args) throws Exception { KeyStore trustStore = KeyStore.getInstance("JKS"); trustStore.load(new FileInputStream("truststore.jks"), "password".toCharArray()); TrustManagerFactory tmf = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm()); tmf.init(trustStore); SSLContext sslContext = SSLContext.getInstance("TLS"); sslContext.init(null, tmf.getTrustManagers(), null); } }
Задача: Загрузить файл через HTTPS.
- Входные данные: URL файла.
- Пример кода:java
import java.io.BufferedInputStream; import java.io.FileOutputStream; import java.net.URL; public class DownloadFile { public static void main(String[] args) throws Exception { String fileUrl = "https://example.com/file.zip"; try (BufferedInputStream in = new BufferedInputStream(new URL(fileUrl).openStream()); FileOutputStream fileOutputStream = new FileOutputStream("downloaded.zip")) { byte[] dataBuffer = new byte[1024]; int bytesRead; while ((bytesRead = in.read(dataBuffer, 0, 1024)) != -1) { fileOutputStream.write(dataBuffer, 0, bytesRead); } } } }
Задача: Проверить, работает ли HTTPS для заданного URL.
- Входные данные: URL для проверки.
- Пример кода:java
import javax.net.ssl.HttpsURLConnection; import java.net.URL; public class CheckHttps { public static void main(String[] args) throws Exception { String url = "https://example.com"; HttpsURLConnection connection = (HttpsURLConnection) new URL(url).openConnection(); connection.setRequestMethod("GET"); int responseCode = connection.getResponseCode(); System.out.println("Response Code: " + responseCode); } }
Задача: Создать Java Keystore и добавить сертификат.
- Входные данные: Путь к сертификату.
- Пример команды:bash
keytool -import -alias mycert -keystore keystore.jks -file mycert.crt -storepass password
Задача: Настроить сервер для использования TLS 1.3.
- Входные данные: Путь к сертификату и ключу.
- Пример кода:java
import javax.net.ssl.*; import java.io.*; import java.security.KeyStore; public class HttpsServerTLS13 { public static void main(String[] args) throws Exception { char[] password = "password".toCharArray(); KeyStore keyStore = KeyStore.getInstance("JKS"); keyStore.load(new FileInputStream("keystore.jks"), password); KeyManagerFactory kmf = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm()); kmf.init(keyStore, password); SSLContext sslContext = SSLContext.getInstance("TLSv1.3"); sslContext.init(kmf.getKeyManagers(), null, null); SSLServerSocketFactory factory = sslContext.getServerSocketFactory(); SSLServerSocket serverSocket = (SSLServerSocket) factory.createServerSocket(8443); System.out.println("HTTPS Server started on port 8443"); while (true) { SSLSocket socket = (SSLSocket) serverSocket.accept(); handleClient(socket); } } private static void handleClient(SSLSocket socket) throws IOException { PrintWriter out = new PrintWriter(socket.getOutputStream(), true); out.println("HTTP/1.1 200 OK"); out.println("Content-Type: text/plain"); out.println(); out.println("Hello, secure world!"); out.flush(); socket.close(); } }
Задача: Защитить клиентский запрос с использованием SSL.
- Входные данные: URL для запроса.
- Пример кода:java
import javax.net.ssl.HttpsURLConnection; import java.io.BufferedReader; import java.io.InputStreamReader; import java.net.URL; public class HttpsClient { public static void main(String[] args) throws Exception { String url = "https://example.com"; HttpsURLConnection connection = (HttpsURLConnection) new URL(url).openConnection(); connection.setRequestMethod("GET"); BufferedReader in = new BufferedReader(new InputStreamReader(connection.getInputStream())); String inputLine; StringBuilder content = new StringBuilder(); while ((inputLine = in.readLine()) != null) { content.append(inputLine); } in.close(); System.out.println("Response: " + content.toString()); } }
Задача: Настроить доверенные сертификаты для клиента.
- Входные данные: Путь к файлу с сертификатом.
- Пример кода:java
import javax.net.ssl.*; import java.io.FileInputStream; import java.security.KeyStore; public class ClientWithTrustStore { public static void main(String[] args) throws Exception { System.setProperty("javax.net.ssl.trustStore", "truststore.jks"); System.setProperty("javax.net.ssl.trustStorePassword", "password"); HttpsURLConnection connection = (HttpsURLConnection) new URL("https://example.com").openConnection(); connection.setRequestMethod("GET"); System.out.println("Response Code: " + connection.getResponseCode()); } }
Задача: Проверить список доступных шифров для SSL.
- Входные данные: Нет.
- Пример кода:java
import javax.net.ssl.SSLServerSocketFactory; public class AvailableCiphers { public static void main(String[] args) { String[] ciphers = SSLServerSocketFactory.getDefault().getSupportedCipherSuites(); for (String cipher : ciphers) { System.out.println(cipher); } } }
OAUTH2
Базовые задачи
Задача: Реализовать клиент для получения токена доступа.
- Входные данные: URL авторизации, client_id, client_secret.
- Пример кода:java
import java.io.OutputStream; import java.net.HttpURLConnection; import java.net.URL; public class OAuthClient { public static void main(String[] args) throws Exception { String url = "https://example.com/oauth/token"; String params = "grant_type=client_credentials&client_id=your_client_id&client_secret=your_client_secret"; HttpURLConnection connection = (HttpURLConnection) new URL(url).openConnection(); connection.setRequestMethod("POST"); connection.setDoOutput(true); connection.setRequestProperty("Content-Type", "application/x-www-form-urlencoded"); try (OutputStream os = connection.getOutputStream()) { os.write(params.getBytes()); } int responseCode = connection.getResponseCode(); System.out.println("Response Code: " + responseCode); } }
Задача: Запросить токен обновления.
- Входные данные: URL авторизации, refresh_token.
- Пример кода:java
import java.io.OutputStream; import java.net.HttpURLConnection; import java.net.URL; public class RefreshToken { public static void main(String[] args) throws Exception { String url = "https://example.com/oauth/token"; String params = "grant_type=refresh_token&refresh_token=your_refresh_token&client_id=your_client_id&client_secret=your_client_secret"; HttpURLConnection connection = (HttpURLConnection) new URL(url).openConnection(); connection.setRequestMethod("POST"); connection.setDoOutput(true); connection.setRequestProperty("Content-Type", "application/x-www-form-urlencoded"); try (OutputStream os = connection.getOutputStream()) { os.write(params.getBytes()); } int responseCode = connection.getResponseCode(); System.out.println("Response Code: " + responseCode); } }
Задача: Реализовать авторизацию с использованием кода авторизации.
- Входные данные: URL авторизации, код, client_id, client_secret.
- Пример кода:java
import java.io.OutputStream; import java.net.HttpURLConnection; import java.net.URL; public class AuthorizationCodeGrant { public static void main(String[] args) throws Exception { String url = "https://example.com/oauth/token"; String params = "grant_type=authorization_code&code=your_authorization_code&redirect_uri=your_redirect_uri&client_id=your_client_id&client_secret=your_client_secret"; HttpURLConnection connection = (HttpURLConnection) new URL(url).openConnection(); connection.setRequestMethod("POST"); connection.setDoOutput(true); connection.setRequestProperty("Content-Type", "application/x-www-form-urlencoded"); try (OutputStream os = connection.getOutputStream()) { os.write(params.getBytes()); } int responseCode = connection.getResponseCode(); System.out.println("Response Code: " + responseCode); } }
Задача: Реализовать клиент для доступа к защищенному ресурсу.
- Входные данные: URL защищенного ресурса и токен доступа.
- Пример кода:java
import java.net.HttpURLConnection; import java.net.URL; public class AccessProtectedResource { public static void main(String[] args) throws Exception { String token = "your_access_token"; String url = "https://example.com/protected/resource"; HttpURLConnection connection = (HttpURLConnection) new URL(url).openConnection(); connection.setRequestMethod("GET"); connection.setRequestProperty("Authorization", "Bearer " + token); int responseCode = connection.getResponseCode(); System.out.println("Response Code: " + responseCode); } }
Задача: Реализовать ручной процесс авторизации.
- Входные данные: client_id и redirect_uri.
- Пример кода:java
public class ManualAuthorization { public static void main(String[] args) { String clientId = "your_client_id"; String redirectUri = "your_redirect_uri"; String authorizationUrl = "https://example.com/oauth/authorize?response_type=code&client_id=" + clientId + "&redirect_uri=" + redirectUri; System.out.println("Visit the following URL to authorize: " + authorizationUrl); } }
Задача: Проверка токена доступа.
- Входные данные: URL проверки токена и токен доступа.
- Пример кода:java
import java.net.HttpURLConnection; import java.net.URL; public class ValidateAccessToken { public static void main(String[] args) throws Exception { String token = "your_access_token"; String url = "https://example.com/oauth/check_token?token=" + token; HttpURLConnection connection = (HttpURLConnection) new URL(url).openConnection(); connection.setRequestMethod("GET"); int responseCode = connection.getResponseCode(); System.out.println("Response Code: " + responseCode); } }
Задача: Получить информацию о пользователе с использованием токена.
- Входные данные: URL для получения информации и токен доступа.
- Пример кода:java
import java.net.HttpURLConnection; import java.net.URL; public class UserInfo { public static void main(String[] args) throws Exception { String token = "your_access_token"; String url = "https://example.com/userinfo"; HttpURLConnection connection = (HttpURLConnection) new URL(url).openConnection(); connection.setRequestMethod("GET"); connection.setRequestProperty("Authorization", "Bearer " + token); int responseCode = connection.getResponseCode(); System.out.println("Response Code: " + responseCode); } }
Задача: Реализовать обновление токена через конфиденциальный клиент.
- Входные данные: URL для обновления токена и refresh_token.
- Пример кода:java
import java.io.OutputStream; import java.net.HttpURLConnection; import java.net.URL; public class ConfidentialClientRefresh { public static void main(String[] args) throws Exception { String url = "https://example.com/oauth/token"; String params = "grant_type=refresh_token&refresh_token=your_refresh_token&client_id=your_client_id&client_secret=your_client_secret"; HttpURLConnection connection = (HttpURLConnection) new URL(url).openConnection(); connection.setRequestMethod("POST"); connection.setDoOutput(true); connection.setRequestProperty("Content-Type", "application/x-www-form-urlencoded"); try (OutputStream os = connection.getOutputStream()) { os.write(params.getBytes()); } int responseCode = connection.getResponseCode(); System.out.println("Response Code: " + responseCode); } }
Задача: Реализовать получение и хранение токенов в базе данных.
- Входные данные: Токены доступа и обновления.
- Пример кода:java
import java.sql.Connection; import java.sql.DriverManager; import java.sql.PreparedStatement; public class StoreTokens { public static void main(String[] args) throws Exception { String accessToken = "your_access_token"; String refreshToken = "your_refresh_token"; Connection connection = DriverManager.getConnection("jdbc:mysql://localhost:3306/your_database", "username", "password"); String sql = "INSERT INTO tokens (access_token, refresh_token) VALUES (?, ?)"; PreparedStatement statement = connection.prepareStatement(sql); statement.setString(1, accessToken); statement.setString(2, refreshToken); statement.executeUpdate(); System.out.println("Tokens stored successfully."); } }
Задача: Реализовать логику выхода из системы с удалением токенов.
- Входные данные: Токен доступа.
- Пример кода:java
import java.sql.Connection; import java.sql.DriverManager; import java.sql.PreparedStatement; public class Logout { public static void main(String[] args) throws Exception { String accessToken = "your_access_token"; Connection connection = DriverManager.getConnection("jdbc:mysql://localhost:3306/your_database", "username", "password"); String sql = "DELETE FROM tokens WHERE access_token = ?"; PreparedStatement statement = connection.prepareStatement(sql); statement.setString(1, accessToken); statement.executeUpdate(); System.out.println("Logged out successfully."); } }
Сложные задачи
Задача: Реализовать полный OAuth2 клиент с поддержкой нескольких потоков.
- Входные данные: URL для авторизации, client_id, client_secret.
- Пример кода:java
import java.io.OutputStream; import java.net.HttpURLConnection; import java.net.URL; public class MultiThreadedOAuthClient { public static void main(String[] args) throws Exception { for (int i = 0; i < 5; i++) { new Thread(() -> { try { String url = "https://example.com/oauth/token"; String params = "grant_type=client_credentials&client_id=your_client_id&client_secret=your_client_secret"; HttpURLConnection connection = (HttpURLConnection) new URL(url).openConnection(); connection.setRequestMethod("POST"); connection.setDoOutput(true); connection.setRequestProperty("Content-Type", "application/x-www-form-urlencoded"); try (OutputStream os = connection.getOutputStream()) { os.write(params.getBytes()); } int responseCode = connection.getResponseCode(); System.out.println("Response Code: " + responseCode); } catch (Exception e) { e.printStackTrace(); } }).start(); } } }
Задача: Реализовать авторизацию с использованием PKCE (Proof Key for Code Exchange).
- Входные данные: client_id, redirect_uri.
- Пример кода:java
import java.security.SecureRandom; public class PKCEAuthorization { public static void main(String[] args) { String clientId = "your_client_id"; String redirectUri = "your_redirect_uri"; String codeVerifier = generateCodeVerifier(); String codeChallenge = generateCodeChallenge(codeVerifier); String authorizationUrl = "https://example.com/oauth/authorize?response_type=code&client_id=" + clientId + "&redirect_uri=" + redirectUri + "&code_challenge=" + codeChallenge; System.out.println("Visit the following URL to authorize: " + authorizationUrl); } private static String generateCodeVerifier() { byte[] randomBytes = new byte[32]; new SecureRandom().nextBytes(randomBytes); return Base64.getUrlEncoder().withoutPadding().encodeToString(randomBytes); } private static String generateCodeChallenge(String codeVerifier) { // SHA-256 hash codeVerifier and return as Base64 URL-encoded string return Base64.getUrlEncoder().withoutPadding().encodeToString(MessageDigest.getInstance("SHA-256").digest(codeVerifier.getBytes())); } }
Задача: Реализовать поддержку авторизации через несколько провайдеров (например, Google, Facebook).
- Входные данные: client_id и secret для каждого провайдера.
- Пример кода:java
public class MultiProviderOAuth { public static void main(String[] args) { String googleClientId = "your_google_client_id"; String facebookClientId = "your_facebook_client_id"; // Generate authorization URL for Google String googleAuthUrl = "https://accounts.google.com/o/oauth2/auth?client_id=" + googleClientId + "&redirect_uri=your_redirect_uri&response_type=code"; System.out.println("Google Authorization URL: " + googleAuthUrl); // Generate authorization URL for Facebook String facebookAuthUrl = "https://www.facebook.com/v10.0/dialog/oauth?client_id=" + facebookClientId + "&redirect_uri=your_redirect_uri&response_type=code"; System.out.println("Facebook Authorization URL: " + facebookAuthUrl); } }
Задача: Реализовать клиент для получения токенов через grant_type "password".
- Входные данные: username и password.
- Пример кода:java
import java.io.OutputStream; import java.net.HttpURLConnection; import java.net.URL; public class PasswordGrantClient { public static void main(String[] args) throws Exception { String url = "https://example.com/oauth/token"; String username = "your_username"; String password = "your_password"; String params = "grant_type=password&username=" + username + "&password=" + password + "&client_id=your_client_id&client_secret=your_client_secret"; HttpURLConnection connection = (HttpURLConnection) new URL(url).openConnection(); connection.setRequestMethod("POST"); connection.setDoOutput(true); connection.setRequestProperty("Content-Type", "application/x-www-form-urlencoded"); try (OutputStream os = connection.getOutputStream()) { os.write(params.getBytes()); } int responseCode = connection.getResponseCode(); System.out.println("Response Code: " + responseCode); } }
Задача: Реализовать логику проверки и обработки токенов с учетом возможных ошибок.
- Входные данные: токен доступа.
- Пример кода:java
import java.net.HttpURLConnection; import java.net.URL; public class TokenValidation { public static void main(String[] args) throws Exception { String token = "your_access_token"; String url = "https://example.com/oauth/check_token?token=" + token; HttpURLConnection connection = (HttpURLConnection) new URL(url).openConnection(); connection.setRequestMethod("GET"); int responseCode = connection.getResponseCode(); if (responseCode == 200) { System.out.println("Token is valid."); } else if (responseCode == 401) { System.out.println("Token is invalid or expired."); } else { System.out.println("Error: " + responseCode); } } }
SOAP: РАБОТА С ПРОТОКОЛОМ SOAP
Базовые задачи
Задача: Создать простой SOAP веб-сервис, который возвращает приветственное сообщение.
- Входные данные: Имя пользователя.
- Пример кода:java
import javax.jws.WebMethod; import javax.jws.WebService; @WebService public class HelloWorldService { @WebMethod public String sayHello(String name) { return "Hello, " + name + "!"; } }
Задача: Создать клиент для вызова вышеупомянутого SOAP сервиса.
- Входные данные: Имя пользователя.
- Пример кода:java
import javax.xml.namespace.QName; import javax.xml.soap.MessageFactory; import javax.xml.soap.SOAPConnection; import javax.xml.soap.SOAPConnectionFactory; import javax.xml.soap.SOAPMessage; public class SOAPClient { public static void main(String[] args) throws Exception { SOAPConnectionFactory soapConnectionFactory = SOAPConnectionFactory.newInstance(); SOAPConnection soapConnection = soapConnectionFactory.createConnection(); String url = "http://localhost:8080/soap/HelloWorldService"; SOAPMessage soapMessage = createSOAPRequest("John"); SOAPMessage soapResponse = soapConnection.call(soapMessage, url); System.out.println("Response: " + soapResponse.getSOAPBody().getTextContent()); soapConnection.close(); } private static SOAPMessage createSOAPRequest(String name) throws Exception { MessageFactory messageFactory = MessageFactory.newInstance(); SOAPMessage soapMessage = messageFactory.createMessage(); soapMessage.getSOAPBody().addChildElement("sayHello").addTextNode(name); soapMessage.saveChanges(); return soapMessage; } }
Задача: Добавить обработку ошибок в SOAP сервис.
- Входные данные: Имя пользователя.
- Пример кода:java
@WebService public class HelloWorldService { @WebMethod public String sayHello(String name) { if (name == null || name.isEmpty()) { throw new IllegalArgumentException("Name cannot be null or empty"); } return "Hello, " + name + "!"; } }
Задача: Создать WSDL для вышеупомянутого сервиса.
- Входные данные: N/A (создание файла).
- Пример:xml
<definitions xmlns="http://schemas.xmlsoap.org/wsdl/" xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/" xmlns:tns="http://example.com/" name="HelloWorldService" targetNamespace="http://example.com/" xmlns:xsd="http://www.w3.org/2001/XMLSchema"> <types> <xsd:schema targetNamespace="http://example.com/"> <xsd:element name="sayHelloRequest"> <xsd:complexType> <xsd:sequence> <xsd:element name="name" type="xsd:string"/> </xsd:sequence> </xsd:complexType> </xsd:element> <xsd:element name="sayHelloResponse"> <xsd:complexType> <xsd:sequence> <xsd:element name="return" type="xsd:string"/> </xsd:sequence> </xsd:complexType> </xsd:element> </xsd:schema> </types> <message name="sayHelloRequest"> <part name="parameters" element="tns:sayHelloRequest"/> </message> <message name="sayHelloResponse"> <part name="parameters" element="tns:sayHelloResponse"/> </message> <portType name="HelloWorldPortType"> <operation name="sayHello"> <input message="tns:sayHelloRequest"/> <output message="tns:sayHelloResponse"/> </operation> </portType> <binding name="HelloWorldBinding" type="tns:HelloWorldPortType"> <soap:binding style="document" transport="http://schemas.xmlsoap.org/soap/http"/> <operation name="sayHello"> <soap:operation soapAction="urn:#sayHello"/> <input> <soap:body use="literal"/> </input> <output> <soap:body use="literal"/> </output> </operation> </binding> <service name="HelloWorldService"> <port name="HelloWorldPort" binding="tns:HelloWorldBinding"> <soap:address location="http://localhost:8080/soap/HelloWorldService"/> </port> </service> </definitions>
Задача: Реализовать метод для получения текущей даты и времени.
- Входные данные: N/A.
- Пример кода:java
@WebService public class TimeService { @WebMethod public String getCurrentTime() { return java.time.LocalDateTime.now().toString(); } }
Задача: Добавить метод для конвертации валют.
- Входные данные: Сумма и валюта.
- Пример кода:java
@WebService public class CurrencyConverterService { @WebMethod public double convert(double amount, String fromCurrency, String toCurrency) { // Здесь можно добавить логику конвертации валют return amount * 1.2; // Пример } }
Задача: Создать SOAP сервис для вычисления факториала числа.
- Входные данные: Целое число.
- Пример кода:java
@WebService public class FactorialService { @WebMethod public long factorial(int number) { if (number < 0) throw new IllegalArgumentException("Number must be non-negative"); return number == 0 ? 1 : number * factorial(number - 1); } }
Задача: Реализовать SOAP сервис для расчета площади круга.
- Входные данные: Радиус.
- Пример кода:java
@WebService public class CircleService { @WebMethod public double calculateArea(double radius) { return Math.PI * radius * radius; } }
Задача: Создать SOAP сервис для конкатенации строк.
- Входные данные: Две строки.
- Пример кода:java
@WebService public class StringService { @WebMethod public String concatenate(String str1, String str2) { return str1 + str2; } }
Задача: Реализовать SOAP сервис, который возвращает массив чисел Фибоначчи.
- Входные данные: Количество чисел.
- Пример кода:java
@WebService public class FibonacciService { @WebMethod public int[] getFibonacci(int count) { int[] fib = new int[count]; fib[0] = 0; if (count > 1) fib[1] = 1; for (int i = 2; i < count; i++) { fib[i] = fib[i - 1] + fib[i - 2]; } return fib; } }
Сложные задачи
Задача: Реализовать SOAP сервис с авторизацией.
- Входные данные: Имя пользователя и пароль.
- Пример кода:java
@WebService public class AuthService { @WebMethod public String login(String username, String password) { // Логика аутентификации if ("admin".equals(username) && "password".equals(password)) { return "Login successful"; } else { throw new SecurityException("Invalid credentials"); } } }
Задача: Создать SOAP сервис с поддержкой нескольких методов и обработкой исключений.
- Входные данные: Разные параметры для различных методов.
- Пример кода:java
@WebService public class MathService { @WebMethod public int add(int a, int b) { return a + b; } @WebMethod public int divide(int a, int b) { if (b == 0) throw new ArithmeticException("Division by zero"); return a / b; } }
Задача: Создать SOAP сервис с поддержкой различных форматов (XML/JSON).
- Входные данные: Запрос в определенном формате.
- Пример кода: (используйте различные библиотеки для поддержки JSON).
Задача: Реализовать сервис, который использует внешние API (например, для получения курса валют).
- Входные данные: Валюта.
- Пример кода: (обращение к внешнему API и обработка ответа).
Задача: Создать сервис с тестами на JUnit.
- Входные данные: Тестовые данные для методов.
- Пример кода:java
import org.junit.jupiter.api.Test; import static org.junit.jupiter.api.Assertions.assertEquals; public class MathServiceTest { private final MathService service = new MathService(); @Test public void testAdd() { assertEquals(5, service.add(2, 3)); } @Test public void testDivide() { assertEquals(2, service.divide(4, 2)); } @Test public void testDivideByZero() { assertThrows(ArithmeticException.class, () -> service.divide(4, 0)); } }
Задача: Создать SOAP сервис, который сохраняет данные в базу данных.
- Входные данные: Данные для сохранения.
- Пример кода: (используйте JDBC для взаимодействия с БД).
Задача: Реализовать сервис, который использует кэширование данных.
- Входные данные: Запрос на получение данных.
- Пример кода: (используйте кэширование через библиотеку).
Задача: Создать сервис, который поддерживает версионирование методов.
- Входные данные: Версия и параметры запроса.
- Пример кода: (реализуйте разные версии одного метода).
Задача: Реализовать SOAP сервис с логированием запросов и ответов.
- Входные данные: Запросы к сервису.
- Пример кода: (используйте логирование через библиотеку).
Задача: Создать сервис, который отправляет уведомления (например, по электронной почте).
- Входные данные: Email и сообщение.
- Пример кода: (используйте библиотеку для отправки почты).
REST: ПРОДВИНУТАЯ РАБОТА С REST API
Базовые задачи
Задача: Создать REST API для управления пользователями (CRUD операции).
- Входные данные: Данные пользователя.
- Пример кода:java
import org.springframework.web.bind.annotation.*; @RestController @RequestMapping("/users") public class UserController { @PostMapping public User createUser(@RequestBody User user) { // Логика для создания пользователя return user; } @GetMapping("/{id}") public User getUser(@PathVariable Long id) { // Логика для получения пользователя по ID return new User(id, "John Doe"); } }
Задача: Реализовать эндпоинт для получения всех пользователей.
- Входные данные: N/A.
- Пример кода:java
@GetMapping public List<User> getAllUsers() { // Логика для получения всех пользователей return List.of(new User(1L, "John Doe"), new User(2L, "Jane Doe")); }
Задача: Добавить обновление данных пользователя по ID.
- Входные данные: ID пользователя и новые данные.
- Пример кода:java
@PutMapping("/{id}") public User updateUser(@PathVariable Long id, @RequestBody User user) { // Логика для обновления пользователя return user; }
Задача: Реализовать удаление пользователя по ID.
- Входные данные: ID пользователя.
- Пример кода:java
@DeleteMapping("/{id}") public void deleteUser(@PathVariable Long id) { // Логика для удаления пользователя }
Задача: Добавить обработку ошибок в контроллер.
- Входные данные: N/A.
- Пример кода:java
@ExceptionHandler(UserNotFoundException.class) public ResponseEntity<String> handleUserNotFound(UserNotFoundException ex) { return ResponseEntity.status(HttpStatus.NOT_FOUND).body(ex.getMessage()); }
Задача: Создать фильтр для логирования запросов.
- Входные данные: N/A.
- Пример кода:java
@Component public class LoggingFilter implements Filter { @Override public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException { System.out.println("Request received"); chain.doFilter(request, response); } }
Задача: Реализовать пагинацию для списка пользователей.
- Входные данные: Номер страницы и размер страницы.
- Пример кода:java
@GetMapping public List<User> getUsers(@RequestParam int page, @RequestParam int size) { // Логика для получения пользователей с пагинацией return List.of(new User(1L, "John Doe"), new User(2L, "Jane Doe")); }
Задача: Создать эндпоинт для поиска пользователей по имени.
- Входные данные: Имя пользователя.
- Пример кода:java
@GetMapping("/search") public List<User> searchUsers(@RequestParam String name) { // Логика для поиска пользователей return List.of(new User(1L, name)); }
Задача: Реализовать фильтрацию пользователей по различным параметрам.
- Входные данные: Разные параметры фильтрации.
- Пример кода: (реализуйте сложный запрос с несколькими параметрами).
Задача: Создать эндпоинт для получения статистики пользователей.
- Входные данные: N/A.
- Пример кода:java
@GetMapping("/stats") public Stats getUserStats() { // Логика для получения статистики return new Stats(100, 50); }
Сложные задачи
Задача: Реализовать аутентификацию и авторизацию в REST API с использованием JWT.
- Входные данные: Логин и пароль.
- Пример кода: (создайте методы для аутентификации и генерации токенов).
Задача: Реализовать CORS (Cross-Origin Resource Sharing) в REST API.
- Входные данные: N/A.
- Пример кода:java
@Configuration public class WebConfig implements WebMvcConfigurer { @Override public void addCorsMappings(CorsRegistry registry) { registry.addMapping("/**").allowedOrigins("http://localhost:3000"); } }
Задача: Создать API для загрузки файлов.
- Входные данные: Файл.
- Пример кода:java
@PostMapping("/upload") public ResponseEntity<String> uploadFile(@RequestParam("file") MultipartFile file) { // Логика для сохранения файла return ResponseEntity.ok("File uploaded successfully"); }
Задача: Реализовать версионирование REST API.
- Входные данные: Версия API.
- Пример кода: (создайте разные контроллеры для разных версий API).
Задача: Создать API для обработки вебхуков.
- Входные данные: Данные вебхука.
- Пример кода:java
@PostMapping("/webhook") public ResponseEntity<String> handleWebhook(@RequestBody WebhookPayload payload) { // Логика обработки вебхука return ResponseEntity.ok("Webhook received"); }
Задача: Реализовать API с использованием HATEOAS.
- Входные данные: N/A.
- Пример кода: (используйте Spring HATEOAS для создания ссылок).
Задача: Создать API для интеграции с внешним сервисом (например, платежным).
- Входные данные: Данные для интеграции.
- Пример кода: (обработка запроса и ответа с внешнего API).
Задача: Реализовать защиту от CSRF (Cross-Site Request Forgery).
- Входные данные: N/A.
- Пример кода: (используйте Spring Security для настройки CSRF).
Задача: Создать REST API с использованием Spring Cloud для микросервисной архитектуры.
- Входные данные: N/A.
- Пример кода: (настройка Eureka для сервисов).
Задача: Реализовать API для отправки уведомлений в реальном времени (например, с использованием WebSockets).
- Входные данные: Данные уведомления.
- Пример кода: (используйте Spring WebSocket для отправки сообщений).
WEBSOCKETS: РЕАЛИЗАЦИЯ ДВУСТОРОННЕГО ВЗАИМОДЕЙСТВИЯ
Базовые задачи
Задача: Создать WebSocket сервер.
- Входные данные: N/A.
- Пример кода:java
import org.springframework.web.socket.TextMessage; import org.springframework.web.socket.WebSocketSession; import org.springframework.web.socket.handler.TextWebSocketHandler; public class MyWebSocketHandler extends TextWebSocketHandler { @Override public void handleTextMessage(WebSocketSession session, TextMessage message) { // Логика обработки сообщения } }
Задача: Реализовать подключение клиента к WebSocket серверу.
- Входные данные: URL сервера.
- Пример кода:java
WebSocketClient client = new StandardWebSocketClient(); WebSocketSession session = client.doHandshake(new MyWebSocketHandler(), "ws://localhost:8080/socket").get();
Задача: Отправить сообщение от клиента на сервер.
- Входные данные: Сообщение.
- Пример кода:java
session.sendMessage(new TextMessage("Hello, server!"));
Задача: Реализовать отправку сообщений от сервера всем подключенным клиентам.
- Входные данные: Сообщение.
- Пример кода:java
@Override public void handleTextMessage(WebSocketSession session, TextMessage message) { for (WebSocketSession webSocketSession : sessions) { webSocketSession.sendMessage(new TextMessage("Message to all: " + message.getPayload())); } }
Задача: Реализовать обработку отключения клиента.
- Входные данные: N/A.
- Пример кода:java
@Override public void afterConnectionClosed(WebSocketSession session, CloseStatus status) { // Логика после отключения клиента }
Задача: Создать клиентскую часть для WebSocket.
- Входные данные: N/A.
- Пример кода: (реализуйте клиентскую часть с использованием JavaScript).
Задача: Реализовать ping/pong механизм для проверки соединения.
- Входные данные: N/A.
- Пример кода:java
@Scheduled(fixedRate = 5000) public void sendPing() { session.sendMessage(new TextMessage("ping")); }
Задача: Реализовать фильтрацию сообщений по типу.
- Входные данные: Тип сообщения.
- Пример кода:java
@Override public void handleTextMessage(WebSocketSession session, TextMessage message) { if (message.getPayload().startsWith("cmd:")) { // Логика обработки команды } }
Задача: Реализовать аутентификацию пользователей через WebSocket.
- Входные данные: Токен аутентификации.
- Пример кода: (реализуйте проверку токена на сервере).
Задача: Создать чат на основе WebSocket.
- Входные данные: Сообщение от пользователя.
- Пример кода: (реализуйте обработку и отображение сообщений).
Сложные задачи
Задача: Реализовать WebSocket сервис с использованием Spring Security.
- Входные данные: Токен аутентификации.
- Пример кода: (настройка безопасности для WebSocket).
Задача: Создать систему уведомлений в реальном времени с использованием WebSocket.
- Входные данные: Уведомления.
- Пример кода: (реализуйте отправку уведомлений через WebSocket).
Задача: Реализовать масштабируемый WebSocket сервер.
- Входные данные: N/A.
- Пример кода: (используйте Redis или другой механизм для масштабирования).
Задача: Создать WebSocket API для обмена сообщениями между пользователями.
- Входные данные: ID пользователя и сообщение.
- Пример кода: (реализуйте отправку сообщений конкретным пользователям).
Задача: Реализовать сохранение истории сообщений.
- Входные данные: Сообщение.
- Пример кода: (сохраните сообщения в базе данных).
Задача: Создать WebSocket сервер для игры в реальном времени.
- Входные данные: Данные игры.
- Пример кода: (обрабатывайте игровые события через WebSocket).
Задача: Реализовать автоматическое восстановление соединения клиента.
- Входные данные: N/A.
- Пример кода: (реализуйте механизм переподключения).
Задача: Создать многоуровневую архитектуру для WebSocket сервиса.
- Входные данные: N/A.
- Пример кода: (реализуйте слои для обработки логики).
Задача: Реализовать пользовательские группы для чата через WebSocket.
- Входные данные: ID группы и сообщение.
- Пример кода: (реализуйте отправку сообщений в группы).
Задача: Создать API для статистики использования WebSocket.
- Входные данные: N/A.
- Пример кода: (реализуйте сбор статистики и создание отчетов).
Примечания
- Каждая задача должна быть дополнена соответствующими зависимостями в проекте, такими как Spring Boot для REST и WebSocket.
- Коды являются примерами и могут потребовать доработки в зависимости от контекста проекта.
THYMELEAF: РАБОТА С ШАБЛОНИЗАТОРОМ В SPRING MVC
Базовые задачи
Задача: Создать простой веб-приложение, использующее Thymeleaf для отображения приветственного сообщения.
- Входные данные: Сообщение (например, "Добро пожаловать!").
- Пример кода:java
@Controller public class HomeController { @GetMapping("/") public String home(Model model) { model.addAttribute("message", "Добро пожаловать!"); return "home"; } }html<!-- home.html --> <!DOCTYPE html> <html xmlns:th="http://www.thymeleaf.org"> <head> <title>Домашняя страница</title> </head> <body> <h1 th:text="${message}"></h1> </body> </html>
Задача: Отобразить список пользователей на странице с использованием Thymeleaf.
- Входные данные: Список пользователей.
- Пример кода:java
@GetMapping("/users") public String users(Model model) { List<User> userList = Arrays.asList(new User("Иван"), new User("Мария")); model.addAttribute("users", userList); return "users"; }html<!-- users.html --> <!DOCTYPE html> <html xmlns:th="http://www.thymeleaf.org"> <head> <title>Пользователи</title> </head> <body> <h2>Список пользователей</h2> <ul> <li th:each="user : ${users}" th:text="${user.name}"></li> </ul> </body> </html>
Задача: Создать форму для добавления нового пользователя.
- Входные данные: Имя пользователя.
- Пример кода:java
@GetMapping("/addUser") public String addUserForm(Model model) { model.addAttribute("user", new User()); return "addUser"; } @PostMapping("/addUser") public String addUser(@ModelAttribute User user) { // Логика для сохранения пользователя return "redirect:/users"; }html<!-- addUser.html --> <!DOCTYPE html> <html xmlns:th="http://www.thymeleaf.org"> <head> <title>Добавить пользователя</title> </head> <body> <h2>Добавить пользователя</h2> <form th:action="@{/addUser}" th:object="${user}" method="post"> <input type="text" th:field="*{name}" placeholder="Имя" required /> <button type="submit">Добавить</button> </form> </body> </html>
Задача: Реализовать отображение информации о пользователе по ID.
- Входные данные: ID пользователя.
- Пример кода:java
@GetMapping("/user/{id}") public String userDetail(@PathVariable Long id, Model model) { User user = userService.findById(id); model.addAttribute("user", user); return "userDetail"; }html<!-- userDetail.html --> <!DOCTYPE html> <html xmlns:th="http://www.thymeleaf.org"> <head> <title>Детали пользователя</title> </head> <body> <h2 th:text="${user.name}"></h2> <p>ID: <span th:text="${user.id}"></span></p> </body> </html>
Задача: Создать страницу с несколькими разделами (разметка с использованием Thymeleaf).
- Входные данные: Разделы с заголовками.
- Пример кода:html
<!-- multiSection.html --> <!DOCTYPE html> <html xmlns:th="http://www.thymeleaf.org"> <head> <title>Несколько разделов</title> </head> <body> <div th:each="section : ${sections}"> <h2 th:text="${section.title}"></h2> <p th:text="${section.content}"></p> </div> </body> </html>
Задача: Реализовать условное отображение элементов (например, кнопка "Удалить" только для администраторов).
- Входные данные: Статус пользователя (администратор или нет).
- Пример кода:html
<button th:if="${user.role == 'ADMIN'}">Удалить</button>
Задача: Создать страницу с пагинацией для списка пользователей.
- Входные данные: Номер страницы.
- Пример кода:java
@GetMapping("/users") public String users(@RequestParam(defaultValue = "0") int page, Model model) { Page<User> userPage = userService.findAll(PageRequest.of(page, 10)); model.addAttribute("users", userPage.getContent()); model.addAttribute("currentPage", page); return "users"; }
Задача: Реализовать систему поиска пользователей по имени.
- Входные данные: Имя для поиска.
- Пример кода:java
@GetMapping("/search") public String searchUsers(@RequestParam String name, Model model) { List<User> userList = userService.findByName(name); model.addAttribute("users", userList); return "users"; }
Задача: Добавить валидацию формы добавления пользователя.
- Входные данные: Имя пользователя (проверка на пустоту).
- Пример кода:java
@PostMapping("/addUser") public String addUser(@Valid @ModelAttribute User user, BindingResult bindingResult) { if (bindingResult.hasErrors()) { return "addUser"; } // Сохранение пользователя return "redirect:/users"; }
Задача: Реализовать функциональность для редактирования пользователя.
- Входные данные: ID пользователя и новые данные.
- Пример кода:java
@GetMapping("/editUser/{id}") public String editUserForm(@PathVariable Long id, Model model) { User user = userService.findById(id); model.addAttribute("user", user); return "editUser"; } @PostMapping("/editUser/{id}") public String editUser(@PathVariable Long id, @ModelAttribute User user) { userService.update(id, user); return "redirect:/users"; }
Задача: Реализовать фильтрацию пользователей по статусу.
- Входные данные: Статус (активный/неактивный).
- Пример кода:java
@GetMapping("/users") public String filterUsers(@RequestParam(required = false) String status, Model model) { List<User> userList = userService.findByStatus(status); model.addAttribute("users", userList); return "users"; }
Задача: Создать страницу для отображения ошибок.
- Входные данные: Сообщение об ошибке.
- Пример кода:java
@ExceptionHandler(Exception.class) public String handleError(Model model, Exception ex) { model.addAttribute("errorMessage", ex.getMessage()); return "error"; }html<!-- error.html --> <!DOCTYPE html> <html xmlns:th="http://www.thymeleaf.org"> <head> <title>Ошибка</title> </head> <body> <h1>Произошла ошибка</h1> <p th:text="${errorMessage}"></p> </body> </html>
Задача: Реализовать функцию логирования входа в систему.
- Входные данные: Логин и пароль.
- Пример кода: (используйте Spring Security для аутентификации).
Задача: Создать страницу с отчетами о пользователях.
- Входные данные: Данные отчетов.
- Пример кода:java
@GetMapping("/reports") public String userReports(Model model) { List<Report> reports = reportService.generateReports(); model.addAttribute("reports", reports); return "reports"; }
Задача: Реализовать функцию фильтрации пользователей по дате регистрации.
- Входные данные: Дата начала и окончания.
- Пример кода:java
@GetMapping("/filterByRegistrationDate") public String filterByRegistrationDate(@RequestParam Date startDate, @RequestParam Date endDate, Model model) { List<User> users = userService.findByRegistrationDate(startDate, endDate); model.addAttribute("users", users); return "users"; }
Сложные задачи
Задача: Создать многоязычное приложение с использованием Thymeleaf.
- Входные данные: Языковые файлы.
- Пример кода: (используйте
MessageSourceдля интернационализации).
Задача: Реализовать AJAX-запросы для динамического обновления содержимого страницы.
- Входные данные: Нажатие кнопки для получения данных.
- Пример кода: (используйте JavaScript для отправки AJAX-запросов к контроллеру).
Задача: Реализовать сохранение состояния форм с использованием сессий.
- Входные данные: Данные формы.
- Пример кода: (сохраните данные формы в сессии).
Задача: Создать адаптивный интерфейс с использованием CSS и Thymeleaf.
- Входные данные: CSS файлы.
- Пример кода: (используйте медиа-запросы в CSS для адаптивности).
Задача: Реализовать роль пользователя (например, администратор, пользователь) и соответствующие права доступа.
- Входные данные: Роли и права доступа.
- Пример кода: (используйте Spring Security для настройки прав доступа).
Задача: Создать RESTful API для управления пользователями с использованием Thymeleaf как фронтенда.
- Входные данные: Запросы к API.
- Пример кода: (используйте
@RestControllerдля создания API).
Задача: Реализовать кэширование страниц с использованием Spring Cache.
- Входные данные: URL страниц.
- Пример кода: (аннотация
@Cacheableдля кэширования).
Задача: Создать шаблон для отправки электронной почты с использованием Thymeleaf.
- Входные данные: Данные для электронной почты.
- Пример кода: (используйте JavaMail для отправки почты).
Задача: Реализовать проверку прав доступа к страницам с использованием аннотации
@PreAuthorize.- Входные данные: Роли и доступ.
- Пример кода:java
@PreAuthorize("hasRole('ADMIN')") @GetMapping("/admin") public String adminPage() { return "admin"; }
Задача: Создать многопользовательское приложение с поддержкой реального времени с использованием WebSocket и Thymeleaf.
- Входные данные: Сообщения от пользователей.
- Пример кода: (реализуйте WebSocket для обработки сообщений).
JAVASCRIPT ИНТЕГРАЦИЯ С JAVA: ИСПОЛЬЗОВАНИЕ NASHORN ИЛИ ВЗАИМОДЕЙСТВИЕ С ФРОНТЕНДОМ
Базовые задачи
Задача: Запустить JavaScript код из Java с использованием Nashorn.
- Входные данные: JavaScript код.
- Пример кода:java
ScriptEngine engine = new ScriptEngineManager().getEngineByName("nashorn"); engine.eval("print('Hello from JavaScript');");
Задача: Передать переменную из Java в JavaScript.
- Входные данные: Значение переменной.
- Пример кода:java
int value = 10; engine.put("value", value); engine.eval("print(value);");
Задача: Создать функцию на JavaScript и вызвать ее из Java.
- Входные данные: Функция JavaScript.
- Пример кода:java
engine.eval("function add(a, b) { return a + b; }"); Invocable invocable = (Invocable) engine; Object result = invocable.invokeFunction("add", 5, 10);
Задача: Передать массив из Java в JavaScript.
- Входные данные: Массив данных.
- Пример кода:java
int[] array = {1, 2, 3, 4}; engine.put("array", array); engine.eval("print(array);");
Задача: Выполнить JavaScript код, который возвращает объект.
- Входные данные: Объект JavaScript.
- Пример кода:java
engine.eval("var obj = {name: 'JavaScript', version: 'ES6'};"); Object obj = engine.get("obj");
Задача: Использовать Nashorn для обработки JSON в JavaScript.
- Входные данные: JSON строка.
- Пример кода:java
String json = "{\"name\":\"John\",\"age\":30}"; engine.eval("var obj = JSON.parse('" + json + "');");
Задача: Создать JavaScript код для обработки событий.
- Входные данные: Событие (например, нажатие кнопки).
- Пример кода: (опишите обработчик на JavaScript).
Задача: Вызвать метод Java из JavaScript.
- Входные данные: Метод Java.
- Пример кода:java
engine.put("javaObject", new JavaObject()); engine.eval("javaObject.method();");
Задача: Обработать асинхронный код на JavaScript из Java.
- Входные данные: Асинхронный код.
- Пример кода: (используйте Promise в JavaScript).
Задача: Создать простое веб-приложение с использованием Java и JavaScript.
- Входные данные: HTML страница.
- Пример кода: (сочетание Java и JavaScript на странице).
Сложные задачи
Задача: Реализовать интеграцию Java и JavaScript для работы с REST API.
- Входные данные: URL API.
- Пример кода: (используйте Fetch API для взаимодействия с Java).
Задача: Реализовать обработку данных с использованием JavaScript и передать их обратно в Java.
- Входные данные: Данные от клиента.
- Пример кода: (сделайте POST запрос с данными).
Задача: Создать интерактивный интерфейс с использованием JavaScript и подключить его к серверу на Java.
- Входные данные: Входные данные от пользователя.
- Пример кода: (используйте AJAX для получения данных).
Задача: Реализовать шаблоны для динамического отображения данных с использованием Thymeleaf и JavaScript.
- Входные данные: Данные для отображения.
- Пример кода: (сочетание Thymeleaf и JavaScript).
Задача: Использовать WebSocket для двустороннего общения между Java и JavaScript.
- Входные данные: Сообщения от клиента.
- Пример кода: (реализуйте сервер на Java и клиент на JavaScript).
Задача: Создать приложение с использованием Nashorn для выполнения сложных вычислений.
- Входные данные: Данные для вычислений.
- Пример кода: (выполните сложные операции на JavaScript).
Задача: Реализовать систему аутентификации с использованием Java и JavaScript.
- Входные данные: Логин и пароль.
- Пример кода: (создайте систему входа на основе AJAX).
Задача: Реализовать клиент-серверную архитектуру с использованием Java и JavaScript.
- Входные данные: Запросы от клиента.
- Пример кода: (сделайте реализацию запросов на сервер).
Задача: Создать SPA (Single Page Application) с использованием Java для бэкенда и JavaScript для фронтенда.
- Входные данные: Различные запросы от клиента.
- Пример кода: (используйте фреймворк Java для создания API).
Задача: Реализовать клиентскую валидацию форм с использованием JavaScript и серверную валидацию с помощью Java.
- Входные данные: Данные формы.
- Пример кода: (используйте JavaScript для валидации на клиенте и Java для серверной проверки).
WEBSOCKET: РЕАЛИЗАЦИЯ РЕАЛЬНОГО ВРЕМЕНИ В ВЕБ-ПРИЛОЖЕНИЯХ
Базовые задачи
Задача: Создать простой WebSocket-сервер.
- Входные данные: Порт для сервера.
- Пример кода:java
import javax.websocket.OnMessage; import javax.websocket.Session; import javax.websocket.server.ServerEndpoint; @ServerEndpoint("/echo") public class EchoServer { @OnMessage public String onMessage(String message, Session session) { return "Echo: " + message; } }
Задача: Создать WebSocket-клиент для подключения к серверу.
- Входные данные: URL сервера.
- Пример кода:java
import javax.websocket.*; import java.net.URI; public class EchoClient { @OnMessage public void onMessage(String message) { System.out.println("Received: " + message); } public static void main(String[] args) throws Exception { WebSocketContainer container = ContainerProvider.getWebSocketContainer(); Session session = container.connectToServer(EchoClient.class, URI.create("ws://localhost:8080/echo")); session.getBasicRemote().sendText("Hello"); } }
Задача: Отправить сообщение от клиента на сервер через WebSocket.
- Входные данные: Сообщение от клиента.
- Пример кода:java
@OnMessage public void onMessage(String message, Session session) throws IOException { System.out.println("Received: " + message); session.getBasicRemote().sendText("Server received: " + message); }
Задача: Создать простой чат-приложение с использованием WebSocket.
- Входные данные: Имя пользователя и сообщение.
- Пример кода:java
@OnMessage public void onMessage(String message, Session session) { broadcastMessage(session, message); } private void broadcastMessage(Session sender, String message) { for (Session session : sessionSet) { if (!session.equals(sender)) { session.getAsyncRemote().sendText(message); } } }
Задача: Реализовать отключение пользователя из WebSocket.
- Входные данные: Сессия пользователя.
- Пример кода:java
@OnClose public void onClose(Session session) { sessionSet.remove(session); System.out.println("Session " + session.getId() + " has ended."); }
Задача: Реализовать хранение активных сессий в сервере.
- Входные данные: Сессия пользователя.
- Пример кода:java
private static Set<Session> sessionSet = ConcurrentHashMap.newKeySet(); @OnOpen public void onOpen(Session session) { sessionSet.add(session); System.out.println("New session: " + session.getId()); }
Задача: Добавить возможность отправки сообщений всем клиентам.
- Входные данные: Сообщение от одного клиента.
- Пример кода:java
public void sendToAll(String message) { for (Session session : sessionSet) { session.getAsyncRemote().sendText(message); } }
Задача: Реализовать обработку ошибок в WebSocket.
- Входные данные: Ошибка во время отправки сообщения.
- Пример кода:java
@OnError public void onError(Session session, Throwable throwable) { System.err.println("Error on session " + session.getId() + ": " + throwable.getMessage()); }
Задача: Создать механизм для отправки уведомлений от сервера.
- Входные данные: Уведомление для пользователей.
- Пример кода:java
public void sendNotification(String notification) { for (Session session : sessionSet) { session.getAsyncRemote().sendText("Notification: " + notification); } }
Задача: Реализовать ping/pong сообщения для проверки активности соединения.
- Входные данные: Периодическая проверка соединения.
- Пример кода:java
@Scheduled(fixedRate = 5000) public void pingAll() { for (Session session : sessionSet) { session.getAsyncRemote().sendText("ping"); } }
Сложные задачи
Задача: Реализовать систему аутентификации для WebSocket-клиентов.
- Входные данные: Токен аутентификации.
- Пример кода: (проверьте токен перед подключением).
Задача: Создать WebSocket-приложение для совместного редактирования текста.
- Входные данные: Изменения текста от клиента.
- Пример кода: (рассылайте изменения всем клиентам).
Задача: Реализовать возможность хранения истории сообщений.
- Входные данные: Сообщения от клиентов.
- Пример кода: (используйте List для хранения сообщений).
Задача: Создать приложение для онлайн-игры с использованием WebSocket.
- Входные данные: Действия игроков.
- Пример кода: (обрабатывайте действия и отправляйте обновления).
Задача: Реализовать функционал приватных сообщений между пользователями.
- Входные данные: Получатель и сообщение.
- Пример кода: (определите логику для отправки сообщений конкретному пользователю).
Задача: Создать мобильное приложение с поддержкой WebSocket.
- Входные данные: Сообщения от мобильного клиента.
- Пример кода: (реализуйте клиентскую часть на мобильном устройстве).
Задача: Реализовать поддержку мультимедийных сообщений через WebSocket.
- Входные данные: Изображения или видео.
- Пример кода: (используйте Base64 для отправки медиафайлов).
Задача: Реализовать режим “не беспокоить” для пользователей.
- Входные данные: Статус пользователя.
- Пример кода: (проверяйте статус перед отправкой сообщений).
Задача: Реализовать функционал ботов, которые могут отвечать на сообщения.
- Входные данные: Сообщения от пользователей.
- Пример кода: (обрабатывайте сообщения и отправляйте ответы).
Задача: Создать веб-приложение с использованием WebSocket для работы с IoT-устройствами.
- Входные данные: Данные от устройств.
- Пример кода: (обрабатывайте данные и отправляйте их на сервер).
RMI (REMOTE METHOD INVOCATION): ВЫЗОВ УДАЛЕННЫХ МЕТОДОВ
Базовые задачи
Задача: Создать простой RMI-сервер.
- Входные данные: Имя удаленного объекта.
- Пример кода:java
import java.rmi.*; import java.rmi.server.*; public class HelloWorld extends UnicastRemoteObject implements Hello { public HelloWorld() throws RemoteException {} public String sayHello() { return "Hello, World!"; } }
Задача: Создать RMI-клиент для обращения к серверу.
- Входные данные: URL RMI-сервера.
- Пример кода:java
import java.rmi.*; public class HelloClient { public static void main(String[] args) { try { Hello stub = (Hello) Naming.lookup("rmi://localhost/Hello"); System.out.println(stub.sayHello()); } catch (Exception e) { System.err.println("Client exception: " + e.toString()); } } }
Задача: Реализовать метод, который возвращает текущее время на сервере.
- Входные данные: Запрос клиента.
- Пример кода:java
public long getCurrentTime() throws RemoteException { return System.currentTimeMillis(); }
Задача: Реализовать удаленный метод для сложения двух чисел.
- Входные данные: Два числа.
- Пример кода:java
public int add(int a, int b) throws RemoteException { return a + b; }
Задача: Реализовать удаленный метод для хранения и получения строки.
- Входные данные: Строка для сохранения.
- Пример кода:java
private String storedString; public void storeString(String str) throws RemoteException { this.storedString = str; } public String getString() throws RemoteException { return storedString; }
Задача: Реализовать удаленный метод для умножения двух чисел.
- Входные данные: Два числа.
- Пример кода:java
public int multiply(int a, int b) throws RemoteException { return a * b; }
Задача: Реализовать метод для получения списка клиентов.
- Входные данные: Запрос на список клиентов.
- Пример кода:java
private List<String> clients = new ArrayList<>(); public List<String> getClients() throws RemoteException { return clients; }
Задача: Реализовать метод для регистрации клиента.
- Входные данные: Имя клиента.
- Пример кода:java
public void registerClient(String name) throws RemoteException { clients.add(name); }
Задача: Реализовать метод для получения статуса сервера.
- Входные данные: Запрос статуса.
- Пример кода:java
public String getStatus() throws RemoteException { return "Server is running."; }
Задача: Реализовать обработку ошибок на сервере.
- Входные данные: Исключение при вызове метода.
- Пример кода:java
public void errorProneMethod() throws RemoteException { throw new RemoteException("An error occurred"); }
Сложные задачи
Задача: Реализовать сложный удаленный метод, который выполняет вычисления.
- Входные данные: Массив чисел.
- Пример кода: (производите сложные вычисления на сервере).
Задача: Создать систему аутентификации для RMI-клиентов.
- Входные данные: Имя пользователя и пароль.
- Пример кода: (проверяйте учетные данные перед выполнением методов).
Задача: Реализовать удаленный метод для работы с коллекциями.
- Входные данные: Коллекция строк.
- Пример кода: (производите операции над коллекцией).
Задача: Создать RMI-приложение для обмена сообщениями между клиентами.
- Входные данные: Сообщения от клиентов.
- Пример кода: (обрабатывайте и отправляйте сообщения другим клиентам).
Задача: Реализовать удаленный метод для загрузки и сохранения файлов.
- Входные данные: Файл для загрузки.
- Пример кода: (позволяйте клиентам загружать файлы на сервер).
Задача: Реализовать механизм шифрования данных при передаче.
- Входные данные: Данные для передачи.
- Пример кода: (шифруйте данные перед отправкой).
Задача: Создать систему управления пользователями с использованием RMI.
- Входные данные: Данные пользователя.
- Пример кода: (реализуйте CRUD-операции для пользователей).
Задача: Реализовать систему уведомлений для клиентов.
- Входные данные: Уведомления от сервера.
- Пример кода: (рассылайте уведомления клиентам).
Задача: Создать RMI-приложение для работы с базой данных.
- Входные данные: Запросы к базе данных.
- Пример кода: (обрабатывайте запросы к базе данных через RMI).
Задача: Реализовать механизм поддержки нескольких клиентов.
- Входные данные: Запросы от нескольких клиентов.
- Пример кода: (обрабатывайте запросы асинхронно).
CORBA: РАБОТА С РАСПРЕДЕЛЕННЫМИ ОБЪЕКТАМИ
Базовые задачи
Задача: Создать простой CORBA-сервер.
- Входные данные: Имя сервиса.
- Пример кода:java
import org.omg.CORBA.*; import org.omg.PortableServer.*; public class HelloServer { public static void main(String[] args) { try { ORB orb = ORB.init(args, null); POA rootPOA = POAHelper.narrow(orb.resolve_initial_references("RootPOA")); rootPOA.the_POAManager().activate(); HelloImpl helloImpl = new HelloImpl(); rootPOA.activate_object(helloImpl); orb.run(); } catch (Exception e) { e.printStackTrace(); } } }
Задача: Создать CORBA-клиент для обращения к серверу.
- Входные данные: URL сервера.
- Пример кода:java
import org.omg.CORBA.*; public class HelloClient { public static void main(String[] args) { try { ORB orb = ORB.init(args, null); String[] arg = { "localhost", "1050" }; String service = orb.resolve_initial_references("Hello"); Hello hello = HelloHelper.narrow(service); System.out.println(hello.sayHello()); } catch (Exception e) { e.printStackTrace(); } } }
Задача: Реализовать метод, который возвращает текущее время на сервере.
- Входные данные: Запрос клиента.
- Пример кода:java
public long getCurrentTime() { return System.currentTimeMillis(); }
Задача: Реализовать удаленный метод для сложения двух чисел.
- Входные данные: Два числа.
- Пример кода:java
public int add(int a, int b) { return a + b; }
Задача: Реализовать удаленный метод для хранения и получения строки.
- Входные данные: Строка для сохранения.
- Пример кода:java
private String storedString; public void storeString(String str) { this.storedString = str; } public String getString() { return storedString; }
Задача: Реализовать удаленный метод для умножения двух чисел.
- Входные данные: Два числа.
- Пример кода:java
public int multiply(int a, int b) { return a * b; }
Задача: Реализовать метод для получения списка клиентов.
- Входные данные: Запрос на список клиентов.
- Пример кода:java
private List<String> clients = new ArrayList<>(); public List<String> getClients() { return clients; }
Задача: Реализовать метод для регистрации клиента.
- Входные данные: Имя клиента.
- Пример кода:java
public void registerClient(String name) { clients.add(name); }
Задача: Реализовать метод для получения статуса сервера.
- Входные данные: Запрос статуса.
- Пример кода:java
public String getStatus() { return "Server is running."; }
Задача: Реализовать обработку ошибок на сервере.
- Входные данные: Исключение при вызове метода.
- Пример кода:java
public void errorProneMethod() { throw new RuntimeException("An error occurred"); }
Сложные задачи
Задача: Реализовать сложный удаленный метод, который выполняет вычисления.
- Входные данные: Массив чисел.
- Пример кода: (производите сложные вычисления на сервере).
Задача: Создать систему аутентификации для CORBA-клиентов.
- Входные данные: Имя пользователя и пароль.
- Пример кода: (проверяйте учетные данные перед выполнением методов).
Задача: Реализовать удаленный метод для работы с коллекциями.
- Входные данные: Коллекция строк.
- Пример кода: (производите операции над коллекцией).
Задача: Создать CORBA-приложение для обмена сообщениями между клиентами.
- Входные данные: Сообщения от клиентов.
- Пример кода: (обрабатывайте и отправляйте сообщения другим клиентам).
Задача: Реализовать удаленный метод для загрузки и сохранения файлов.
- Входные данные: Файл для загрузки.
- Пример кода: (позволяйте клиентам загружать файлы на сервер).
Задача: Реализовать механизм шифрования данных при передаче.
- Входные данные: Данные для передачи.
- Пример кода: (шифруйте данные перед отправкой).
Задача: Создать систему управления пользователями с использованием CORBA.
- Входные данные: Данные пользователя.
- Пример кода: (реализуйте CRUD-операции для пользователей).
Задача: Реализовать систему уведомлений для клиентов.
- Входные данные: Уведомления от сервера.
- Пример кода: (рассылайте уведомления клиентам).
Задача: Создать CORBA-приложение для работы с базой данных.
- Входные данные: Запросы к базе данных.
- Пример кода: (обрабатывайте запросы к базе данных через CORBA).
Задача: Реализовать механизм поддержки нескольких клиентов.
- Входные данные: Запросы от нескольких клиентов.
- Пример кода: (обрабатывайте запросы асинхронно).
BLE (BLUETOOTH LOW ENERGY)
Базовые задачи (25 задач)
Задача: Найти доступные BLE устройства.
- Входные данные: Никакие.
- Пример кода:java
BluetoothAdapter bluetoothAdapter = BluetoothAdapter.getDefaultAdapter(); bluetoothAdapter.startDiscovery();
Задача: Проверить, включен ли Bluetooth.
- Входные данные: Никакие.
- Пример кода:java
if (bluetoothAdapter.isEnabled()) { System.out.println("Bluetooth включен."); }
Задача: Включить Bluetooth программно.
- Входные данные: Никакие.
- Пример кода:java
bluetoothAdapter.enable();
Задача: Получить список спаренных устройств.
- Входные данные: Никакие.
- Пример кода:java
Set<BluetoothDevice> pairedDevices = bluetoothAdapter.getBondedDevices(); for (BluetoothDevice device : pairedDevices) { System.out.println(device.getName() + " - " + device.getAddress()); }
Задача: Подключиться к BLE устройству.
- Входные данные: Адрес устройства.
- Пример кода:java
BluetoothDevice device = bluetoothAdapter.getRemoteDevice("00:11:22:33:AA:BB"); device.connectGatt(context, false, bluetoothGattCallback);
Задача: Отключить подключенное BLE устройство.
- Входные данные: Экземпляр GATT.
- Пример кода:java
bluetoothGatt.disconnect();
Задача: Найти сервисы на устройстве.
- Входные данные: Подключенное устройство.
- Пример кода:java
List<BluetoothGattService> services = bluetoothGatt.getServices();
Задача: Найти характеристики конкретного сервиса.
- Входные данные: Экземпляр сервиса.
- Пример кода:java
BluetoothGattCharacteristic characteristic = service.getCharacteristic(UUID.fromString("00002a37-0000-1000-8000-00805f9b34fb"));
Задача: Прочитать характеристику BLE устройства.
- Входные данные: Характеристика.
- Пример кода:java
bluetoothGatt.readCharacteristic(characteristic);
Задача: Записать значение в характеристику устройства.
- Входные данные: Значение и характеристика.
- Пример кода:java
characteristic.setValue(new byte[]{0x01}); bluetoothGatt.writeCharacteristic(characteristic);
Задача: Активировать уведомления для характеристики.
- Входные данные: Характеристика.
- Пример кода:java
bluetoothGatt.setCharacteristicNotification(characteristic, true);
Задача: Получить RSSI уровня сигнала устройства.
- Входные данные: Подключенное устройство.
- Пример кода:java
bluetoothGatt.readRemoteRssi();
Задача: Проверить поддержку BLE на устройстве.
- Входные данные: Никакие.
- Пример кода:java
if (context.getPackageManager().hasSystemFeature(PackageManager.FEATURE_BLUETOOTH_LE)) { System.out.println("BLE поддерживается"); }
Задача: Отключить Bluetooth программно.
- Входные данные: Никакие.
- Пример кода:java
bluetoothAdapter.disable();
Задача: Включить уведомления об изменении характеристик.
- Входные данные: Характеристика.
- Пример кода:java
bluetoothGatt.setCharacteristicNotification(characteristic, true);
Задача: Отправить данные на BLE устройство.
- Входные данные: Данные для отправки.
- Пример кода:java
characteristic.setValue("Hello BLE"); bluetoothGatt.writeCharacteristic(characteristic);
Задача: Найти конкретное BLE устройство по имени.
- Входные данные: Имя устройства.
- Пример кода:java
if (device.getName().equals("MyBLEDevice")) { System.out.println("Устройство найдено"); }
Задача: Показать список услуг, предоставляемых устройством.
- Входные данные: Подключенное устройство.
- Пример кода:java
for (BluetoothGattService service : bluetoothGatt.getServices()) { System.out.println(service.getUuid()); }
Задача: Реализовать callback для обработки изменения характеристик.
- Входные данные: Измененные данные.
- Пример кода:java
public void onCharacteristicChanged(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic) { byte[] value = characteristic.getValue(); System.out.println("Характеристика изменена: " + new String(value)); }
Задача: Установить максимальную мощность передатчика.
- Входные данные: Никакие.
- Пример кода:java
bluetoothGatt.requestMtu(512);
Задача: Отменить обнаружение BLE устройств.
- Входные данные: Никакие.
- Пример кода:java
bluetoothAdapter.cancelDiscovery();
Задача: Получить устройство по его MAC адресу.
- Входные данные: MAC адрес.
- Пример кода:java
BluetoothDevice device = bluetoothAdapter.getRemoteDevice("00:11:22:33:44:55");
Задача: Считать данные с устройства по BLE.
- Входные данные: Подключенное устройство.
- Пример кода:java
bluetoothGatt.readCharacteristic(characteristic);
Задача: Реализовать тайм-аут для подключения к BLE устройству.
- Входные данные: Время тайм-аута.
- Пример кода:java
Handler handler = new Handler(); handler.postDelayed(() -> { if (!connected) { bluetoothGatt.disconnect(); } }, 10000);
Задача: Отключить уведомления для характеристики.
- Входные данные: Характеристика.
- Пример кода:java
bluetoothGatt.setCharacteristicNotification(characteristic, false);
Сложные задачи (10 задач)
Задача: Реализовать автоматическое повторное подключение к BLE устройству при разрыве связи.
- Входные данные: Подключенное устройство.
- Пример кода:java
public void onConnectionStateChange(BluetoothGatt gatt, int status, int newState) { if (newState == BluetoothProfile.STATE_DISCONNECTED) { gatt.connect(); } }
Задача: Реализовать работу с несколькими BLE устройствами одновременно.
- Входные данные: Несколько устройств.
- Пример кода: (обработайте каждое устройство отдельно).
Задача: Реализовать передачу больших данных через BLE с использованием MTU.
- Входные данные: Данные для передачи.
- Пример кода: (разбейте данные на части и отправьте).
Задача: Настроить приоритет передачи данных для устройства BLE.
- Входные данные: Устройство и приоритет.
- Пример кода:java
bluetoothGatt.requestConnectionPriority(BluetoothGatt.CONNECTION_PRIORITY_HIGH);
Задача: Реализовать обновление прошивки устройства через BLE.
- Входные данные: Файл прошивки.
- Пример кода: (загрузите файл на устройство).
WI-FI
Базовые задачи (25 задач)
Задача: Получить список доступных Wi-Fi сетей.
- Входные данные: Никакие.
- Пример кода:java
WifiManager wifiManager = (WifiManager) context.getSystemService(Context.WIFI_SERVICE); List<ScanResult> scanResults = wifiManager.getScanResults();
Задача: Подключиться к Wi-Fi сети.
- Входные данные: SSID и пароль.
- Пример кода:java
WifiConfiguration wifiConfig = new WifiConfiguration(); wifiConfig.SSID = String.format("\"%s\"", "SSID"); wifiConfig.preSharedKey = String.format("\"%s\"", "password"); int netId = wifiManager.addNetwork(wifiConfig); wifiManager.disconnect(); wifiManager.enableNetwork(netId, true); wifiManager.reconnect();
Задача: Отключиться от текущей Wi-Fi сети.
- Входные данные: Никакие.
- Пример кода:java
wifiManager.disconnect();
Задача: Проверить статус Wi-Fi соединения.
- Входные данные: Никакие.
- Пример кода:java
NetworkInfo networkInfo = connectivityManager.getNetworkInfo(ConnectivityManager.TYPE_WIFI); if (networkInfo.isConnected()) { System.out.println("Подключен к Wi-Fi"); }
Задача: Получить информацию о текущем Wi-Fi соединении.
- Входные данные: Никакие.
- Пример кода:java
WifiInfo wifiInfo = wifiManager.getConnectionInfo(); System.out.println("SSID: " + wifiInfo.getSSID());
Задача: Проверить, включен ли Wi-Fi.
- Входные данные: Никакие.
- Пример кода:java
if (wifiManager.isWifiEnabled()) { System.out.println("Wi-Fi включен"); }
Задача: Включить Wi-Fi программно.
- Входные данные: Никакие.
- Пример кода:java
wifiManager.setWifiEnabled(true);
Задача: Отключить Wi-Fi программно.
- Входные данные: Никакие.
- Пример кода:java
wifiManager.setWifiEnabled(false);
Задача: Изменить настройки существующей Wi-Fi сети.
- Входные данные: SSID и новый пароль.
- Пример кода:java
WifiConfiguration config = ...; // Найдите существующую конфигурацию config.preSharedKey = String.format("\"%s\"", "new_password"); wifiManager.updateNetwork(config);
Задача: Получить MAC-адрес устройства.
- Входные данные: Никакие.
- Пример кода:java
String macAddress = wifiInfo.getMacAddress(); System.out.println("MAC-адрес: " + macAddress);
Задача: Получить список ранее подключенных сетей.
- Входные данные: Никакие.
- Пример кода:java
List<WifiConfiguration> configuredNetworks = wifiManager.getConfiguredNetworks();
Задача: Удалить Wi-Fi сеть.
- Входные данные: SSID.
- Пример кода:java
int netId = ...; // Получите netId wifiManager.removeNetwork(netId);
Задача: Реализовать механизм автоматического подключения к известной Wi-Fi сети.
- Входные данные: SSID и пароль.
- Пример кода: (вызовите код подключения из предыдущих задач).
Задача: Получить информацию о скорости Wi-Fi соединения.
- Входные данные: Никакие.
- Пример кода:java
int linkSpeed = wifiInfo.getLinkSpeed(); // Скорость в Mbps
Задача: Изменить настройки прокси для Wi-Fi соединения.
- Входные данные: Адрес и порт прокси.
- Пример кода: (измените конфигурацию Wi-Fi сети).
Задача: Получить список всех доступных сетей с их уровнями сигнала.
- Входные данные: Никакие.
- Пример кода:java
for (ScanResult result : scanResults) { System.out.println(result.SSID + " - " + result.level); }
Задача: Включить режим "горячей точки".
- Входные данные: Имя и пароль точки доступа.
- Пример кода: (используйте соответствующий API).
Задача: Создать Wi-Fi точку доступа программно.
- Входные данные: SSID и пароль.
- Пример кода: (используйте соответствующий API).
Задача: Реализовать механизм проверки доступности интернета через Wi-Fi.
- Входные данные: Никакие.
- Пример кода: (отправьте HTTP-запрос и проверьте ответ).
Задача: Реализовать систему уведомлений о подключении/отключении от Wi-Fi сети.
- Входные данные: Никакие.
- Пример кода: (используйте BroadcastReceiver).
Задача: Реализовать обновление прошивки через Wi-Fi.
- Входные данные: URL файла прошивки.
- Пример кода: (используйте HTTP-запрос).
Задача: Реализовать систему мониторинга состояния Wi-Fi соединения.
- Входные данные: Никакие.
- Пример кода: (используйте Timer для периодической проверки).
Задача: Реализовать механизм ограничения доступа к Wi-Fi сети для определенных устройств.
- Входные данные: MAC-адрес устройства.
- Пример кода: (измените настройки роутера).
Задача: Реализовать автоматическое отключение от Wi-Fi после определенного времени.
- Входные данные: Время отключения.
- Пример кода:java
new Timer().schedule(new TimerTask() { @Override public void run() { wifiManager.disconnect(); } }, delay);
Задача: Реализовать механизм оценки качества Wi-Fi соединения.
- Входные данные: Никакие.
- Пример кода: (используйте уровень сигнала и скорость).
Сложные задачи (10 задач)
Задача: Реализовать функцию автоматического переключения между Wi-Fi и мобильными данными в зависимости от качества соединения.
- Входные данные: Никакие.
- Пример кода: (используйте NetworkCallback).
Задача: Реализовать систему для управления несколькими Wi-Fi соединениями.
- Входные данные: Несколько SSID и паролей.
- Пример кода: (обработайте каждую сеть).
Задача: Реализовать функционал проверки доступности Wi-Fi сети и автоматического подключения.
- Входные данные: SSID.
- Пример кода: (проверьте доступность и подключитесь).
Задача: Создать Wi-Fi сеть с заданными параметрами и безопасностью.
- Входные данные: SSID, пароль, тип безопасности.
- Пример кода: (используйте соответствующий API).
Задача: Реализовать систему мониторинга Wi-Fi соединения и уведомления о потере соединения.
- Входные данные: Никакие.
- Пример кода: (используйте BroadcastReceiver).
Задача: Реализовать систему контроля за использованием интернет-трафика через Wi-Fi.
- Входные данные: Никакие.
- Пример кода: (отслеживайте трафик).
Задача: Реализовать систему для ограничения доступа к интернету для определенных приложений через Wi-Fi.
- Входные данные: Идентификаторы приложений.
- Пример кода: (измените настройки роутера).
Задача: Реализовать функционал управления качеством сервиса (QoS) для Wi-Fi соединения.
- Входные данные: Приоритеты для приложений.
- Пример кода: (используйте соответствующий API).
Задача: Реализовать систему шифрования данных, передаваемых через Wi-Fi.
- Входные данные: Данные для передачи.
- Пример кода: (шифруйте данные перед отправкой).
Задача: Создать приложение для анализа качества Wi-Fi соединения.
- Входные данные: Никакие.
- Пример кода: (используйте уровень сигнала и скорость).
LORA
Базовые задачи (25 задач)
Задача: Подключиться к LoRa сети.
- Входные данные: Никакие.
- Пример кода: (инициализация LoRa модуля).
Задача: Отправить сообщение через LoRa.
- Входные данные: Сообщение.
- Пример кода:java
lora.send("Hello World");
Задача: Получить сообщение через LoRa.
- Входные данные: Никакие.
- Пример кода:java
String message = lora.receive();
Задача: Настроить параметры LoRa соединения.
- Входные данные: Частота и мощность передачи.
- Пример кода:java
lora.setFrequency(868E6); lora.setTxPower(14);
Задача: Проверить статус LoRa соединения.
- Входные данные: Никакие.
- Пример кода:java
if (lora.isConnected()) { System.out.println("Подключено к LoRa сети"); }
Задача: Отправить данные с датчика через LoRa.
- Входные данные: Данные с датчика.
- Пример кода:java
float sensorData = getSensorData(); lora.send(String.valueOf(sensorData));
Задача: Реализовать механизм подтверждения получения сообщения.
- Входные данные: Никакие.
- Пример кода: (добавьте ACK к отправляемым сообщениям).
Задача: Реализовать систему для передачи данных на определенные интервалы времени.
- Входные данные: Интервал.
- Пример кода:java
Timer timer = new Timer(); timer.schedule(new TimerTask() { @Override public void run() { lora.send("Periodic message"); } }, 0, interval);
Задача: Настроить параметры безопасности для LoRa соединения.
- Входные данные: Ключи безопасности.
- Пример кода: (установите ключи).
Задача: Реализовать систему для отправки сообщений в случае потери соединения.
- Входные данные: Никакие.
- Пример кода: (отправьте сообщение при восстановлении соединения).
Задача: Создать систему для контроля уровня сигнала LoRa.
- Входные данные: Никакие.
- Пример кода:java
int signalLevel = lora.getSignalLevel();
Задача: Реализовать механизм обработки ошибок передачи сообщений.
- Входные данные: Никакие.
- Пример кода: (обработайте исключения).
Задача: Отправить данные в виде JSON через LoRa.
- Входные данные: Данные.
- Пример кода:java
String jsonData = "{\"sensor\": 25}"; lora.send(jsonData);
Задача: Получить данные в виде JSON через LoRa.
- Входные данные: Никакие.
- Пример кода:java
String jsonData = lora.receive();
Задача: Реализовать систему для настройки параметров LoRa через командную строку.
- Входные данные: Команды.
- Пример кода: (обработайте команды).
Задача: Реализовать систему для отправки данных в многоточечную сеть.
- Входные данные: Адреса получателей.
- Пример кода: (отправьте данные на несколько адресов).
Задача: Реализовать механизм мониторинга состояния LoRa соединения.
- Входные данные: Никакие.
- Пример кода: (периодическая проверка состояния).
Задача: Реализовать систему для управления несколькими LoRa модулями.
- Входные данные: Никакие.
- Пример кода: (инициализируйте и управляйте модулями).
Задача: Реализовать систему для передачи данных с разных датчиков.
- Входные данные: Данные с датчиков.
- Пример кода: (объедините данные и отправьте).
Задача: Реализовать функционал для обновления прошивки через LoRa.
- Входные данные: URL прошивки.
- Пример кода: (используйте соответствующий механизм).
Задача: Реализовать систему для управления устройствами через LoRa.
- Входные данные: Команды управления.
- Пример кода: (отправьте команды и получите ответ).
Задача: Реализовать систему для сбора данных с нескольких устройств.
- Входные данные: Никакие.
- Пример кода: (обрабатывайте данные от нескольких источников).
Задача: Реализовать систему для передачи аудио данных через LoRa.
- Входные данные: Аудио данные.
- Пример кода: (обработайте аудио и отправьте).
Задача: Реализовать систему для передачи видео данных через LoRa.
- Входные данные: Видео данные.
- Пример кода: (обработайте видео и отправьте).
Задача: Реализовать механизм для управления режимами LoRa.
- Входные данные: Режимы.
- Пример кода: (измените настройки модуля).
Сложные задачи (10 задач)
Задача: Реализовать систему для передачи данных с использованием шифрования.
- Входные данные: Данные для отправки.
- Пример кода: (шифруйте данные перед отправкой).
Задача: Реализовать систему для автоматического повторного отправления сообщений.
- Входные данные: Никакие.
- Пример кода: (реализуйте логику повторной отправки).
Задача: Реализовать систему для анализа производительности LoRa соединения.
- Входные данные: Никакие.
- Пример кода: (отслеживайте время отправки и получения).
Задача: Реализовать систему для управления несколькими передатчиками и приемниками.
- Входные данные: Никакие.
- Пример кода: (инициализируйте и управляйте передатчиками/приемниками).
Задача: Реализовать систему для анализа данных, полученных через LoRa.
- Входные данные: Никакие.
- Пример кода: (обработайте и проанализируйте полученные данные).
Задача: Реализовать систему для передачи данных с использованием различных протоколов.
- Входные данные: Протоколы.
- Пример кода: (измените настройки протоколов).
Задача: Реализовать систему для передачи данных в режиме реального времени.
- Входные данные: Данные.
- Пример кода: (используйте асинхронные операции).
Задача: Реализовать систему для создания отчетов по использованию LoRa соединения.
- Входные данные: Никакие.
- Пример кода: (соберите данные и сформируйте отчет).
Задача: Реализовать систему для автоматического управления параметрами LoRa соединения.
- Входные данные: Условия.
- Пример кода: (измените параметры на основе условий).
Задача: Реализовать систему для интеграции LoRa с другими системами (например, IoT).
- Входные данные: API других систем.
- Пример кода: (создайте интеграцию).